Reputation: 1928
I have a timeserie dataframe filled with 0 and a various number of columns and I would like to fill values in diagonal with 100 starting by the first row and the first column. I could use the solution proposed in the question bellow but it stops after value of the last column has been filled. Set values on the diagonal of pandas.DataFrame
How could I make it repeat over all rows?
This is how my dataframe looks like:
A B
2020-05-02 23:00:00+00:00 0.0 0.0
2020-05-03 00:00:00+00:00 0.0 0.0
2020-05-03 01:00:00+00:00 0.0 0.0
2020-05-03 02:00:00+00:00 0.0 0.0
2020-05-03 03:00:00+00:00 0.0 0.0
But as you can see using Numpy fill_diagonal doesn't complete the job.
import numpy as np
np.fill_diagonal(df.values, 0)
A B
2020-05-02 23:00:00+00:00 100.0 0.0
2020-05-03 00:00:00+00:00 0.0 100.0
2020-05-03 01:00:00+00:00 0.0 0.0
2020-05-03 02:00:00+00:00 0.0 0.0
2020-05-03 03:00:00+00:00 0.0 0.0
When there are 2 columns I would like is something like this:
A B
2020-05-02 23:00:00+00:00 100.0 0.0
2020-05-03 00:00:00+00:00 0.0 100.0
2020-05-03 01:00:00+00:00 100.0 0.0
2020-05-03 02:00:00+00:00 0.0 100.0
2020-05-03 03:00:00+00:00 100.0 0.0
Upvotes: 3
Views: 228
Reputation: 8768
Here is a way using np.identity
and np.tile
s = df.shape
df.where(np.tile(np.identity(s[-1]),(s[0],1))[:s[0]] != 1,100)
or
r,c = df.shape
df.mask(np.tile(np.identity(c),(-(r//-c),1))[:r] == 1,100)
Upvotes: 1
Reputation: 88236
Here's a numpy based approach, reshaping based on the amount of columns and slice assigning back with a given value:
def fill_wrapped_diag(a, fill_val):
r,c = a.shape
r_left = c-r%c
a_ext = np.pad(a, ((0,r_left),(0,0)))
a_r = a_ext.reshape((r+r_left)//c, -1)
a_r[:,::c+1] = fill_val
return a_r.reshape(a_ext.shape)[:-r_left]
df[:] = fill_wrapped_diag(df.values, 100)
print(df)
A B
2020-05-02-23:00:00+00:00 100.0 0.0
2020-05-03-00:00:00+00:00 0.0 100.0
2020-05-03-01:00:00+00:00 100.0 0.0
2020-05-03-02:00:00+00:00 0.0 100.0
2020-05-03-03:00:00+00:00 100.0 0.0
Some other examples:
a = np.zeros((8,4))
fill_wrapped_diag(a, fill_val=100)
array([[100., 0., 0., 0.],
[ 0., 100., 0., 0.],
[ 0., 0., 100., 0.],
[ 0., 0., 0., 100.],
[100., 0., 0., 0.],
[ 0., 100., 0., 0.],
[ 0., 0., 100., 0.],
[ 0., 0., 0., 100.]])
a = np.random.randint(0,10,(7,3))
fill_wrapped_diag(a, fill_val=75)
array([[75, 8, 8],
[ 4, 75, 7],
[ 3, 5, 75],
[75, 5, 5],
[ 5, 75, 2],
[ 3, 6, 75],
[75, 1, 8]])
Upvotes: 3