how to shift non nan value in multiple columns row wise by group?
Question:
so i have data frame as below
A1
A2
A3
A4
A5
A6
1
nan
3
7
nan
8
nan
5
nan
11
9
nan
54
6
84
12
3
nan
10
nan
nan
16
nan
45
12
93
13
31
5
91
73
nan
45
nan
nan
9
i want to shift the whole data frame n rows such that it skips nan rows but still preserve it.
desire output:
for n =2
A1
A2
A3
A4
A5
A6
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
7
nan
nan
1
nan
nan
11
nan
nan
54
5
3
12
9
8
10
nan
84
nan
nan
45
i tried the following:
df['dummy'] = df.apply(lambda x: 1 if pd.notnull(x[column]) else 0, axis=1)
df['dummy2'] = df.groupby(['dummy'])[column].shift(n)
df[column] = df.apply(lambda x: x['dummy2'] if x['dummy']==1 else x[column], axis=1)
which is good if there is only a few columns i need to shift.
i also tried the applymap function
dummy_df = df.applymap(lambda x: 1 if pd.notnull(x) else 0)
which returns a dummy data frame to separate groups that i want to shift, just have no idea what to do next with it.
the problem is that there are thousands of columns i need to shift row wise.
Is there any ways i can do this using minimum loops? And are there any ways to do it with groupby function using dummy_df?
Answers:
try this:
tmp = df.apply(
lambda s: s.sort_values(
key=lambda v: pd.notnull(v)
).values
)
res = tmp.shift(2)
res
Use lambda function with Series.dropna
and Series.shift
:
df = df.apply(lambda x: x.dropna().shift(2))
print (df)
A1 A2 A3 A4 A5 A6
0 NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN 7.0 NaN NaN
3 1.0 NaN NaN 11.0 NaN NaN
4 54.0 5.0 3.0 12.0 9.0 8.0
5 10.0 NaN 84.0 NaN NaN 45.0
so i have data frame as below
A1 | A2 | A3 | A4 | A5 | A6 |
---|---|---|---|---|---|
1 | nan | 3 | 7 | nan | 8 |
nan | 5 | nan | 11 | 9 | nan |
54 | 6 | 84 | 12 | 3 | nan |
10 | nan | nan | 16 | nan | 45 |
12 | 93 | 13 | 31 | 5 | 91 |
73 | nan | 45 | nan | nan | 9 |
i want to shift the whole data frame n rows such that it skips nan rows but still preserve it.
desire output:
for n =2
A1 | A2 | A3 | A4 | A5 | A6 |
---|---|---|---|---|---|
nan | nan | nan | nan | nan | nan |
nan | nan | nan | nan | nan | nan |
nan | nan | nan | 7 | nan | nan |
1 | nan | nan | 11 | nan | nan |
54 | 5 | 3 | 12 | 9 | 8 |
10 | nan | 84 | nan | nan | 45 |
i tried the following:
df['dummy'] = df.apply(lambda x: 1 if pd.notnull(x[column]) else 0, axis=1)
df['dummy2'] = df.groupby(['dummy'])[column].shift(n)
df[column] = df.apply(lambda x: x['dummy2'] if x['dummy']==1 else x[column], axis=1)
which is good if there is only a few columns i need to shift.
i also tried the applymap function
dummy_df = df.applymap(lambda x: 1 if pd.notnull(x) else 0)
which returns a dummy data frame to separate groups that i want to shift, just have no idea what to do next with it.
the problem is that there are thousands of columns i need to shift row wise.
Is there any ways i can do this using minimum loops? And are there any ways to do it with groupby function using dummy_df?
try this:
tmp = df.apply(
lambda s: s.sort_values(
key=lambda v: pd.notnull(v)
).values
)
res = tmp.shift(2)
res
Use lambda function with Series.dropna
and Series.shift
:
df = df.apply(lambda x: x.dropna().shift(2))
print (df)
A1 A2 A3 A4 A5 A6
0 NaN NaN NaN NaN NaN NaN
1 NaN NaN NaN NaN NaN NaN
2 NaN NaN NaN 7.0 NaN NaN
3 1.0 NaN NaN 11.0 NaN NaN
4 54.0 5.0 3.0 12.0 9.0 8.0
5 10.0 NaN 84.0 NaN NaN 45.0