一次使用多个 fillna 策略的 groupby (pandas)
groupby with multiple fillna strategies at once (pandas)
如何按一列分组,然后在每个组内同时对其他列应用多个 fillna 策略?多重含义:
- 如果组中第一个,用零替换,然后填充直到到达第一个数据点
- 尾随的 NaN 被填充
- 对于数据点之间的所有 NaN,bfill
- 如果全是 NaN,就不要管组
基本上,我有以下数据框:
A B C
0 A NaN NaN
1 A NaN NaN
2 A 1.0 10.0
3 A NaN NaN
4 B NaN NaN
5 B 2.0 20.0
6 B NaN 20.0
7 B NaN NaN
8 C NaN NaN
9 C NaN NaN
10 C NaN NaN
11 C NaN 30.0
我希望它变成:
A B C
0 A 0 0
1 A 0 0
2 A 1.0 10.0
3 A 1.0 10.0
4 B 0 0
5 B 2.0 20.0
6 B 2.0 20.0
7 B 2.0 20.0
8 C NaN 0
9 C NaN 0
10 C NaN 0
11 C NaN 30.0
我尝试使用 df.groupby('A').nth(1)
获取第一个元素并有条件地继续,但是 groupby
创建的新索引不是原始索引(即 0,4,8),无论如何我是否通过 .reset_index()
选项。
数据框重建代码:
df = pd.DataFrame({'A' : ["A", "A", "A", "A",
"B", "B", "B", "B","C", "C", "C", "C"],
'B' : [np.nan, np.nan, 1, np.nan,
np.nan, 2, np.nan, np.nan,
np.nan, np.nan, np.nan, np.nan],
'C' : [np.nan, np.nan, 10, np.nan,
np.nan, 20, 20, np.nan,
np.nan, np.nan, np.nan, 30]})
一个可能的想法是在 A
上使用 DataFrame.groupby
,然后使用自定义转换器函数:
def fx(s):
if s.isna().all():
return s
elif pd.isna(s.iloc[0]):
s.iloc[0] = 0
s = s.ffill().bfill()
return s
df[['B', 'C']] = df.groupby('A')[['B', 'C']].transform(fx)
# print(df)
A B C
0 A 0.0 0.0
1 A 0.0 0.0
2 A 1.0 10.0
3 A 1.0 10.0
4 B 0.0 0.0
5 B 2.0 20.0
6 B 2.0 20.0
7 B 2.0 20.0
8 C NaN 0.0
9 C NaN 0.0
10 C NaN 0.0
11 C NaN 30.0
如何按一列分组,然后在每个组内同时对其他列应用多个 fillna 策略?多重含义:
- 如果组中第一个,用零替换,然后填充直到到达第一个数据点
- 尾随的 NaN 被填充
- 对于数据点之间的所有 NaN,bfill
- 如果全是 NaN,就不要管组
基本上,我有以下数据框:
A B C
0 A NaN NaN
1 A NaN NaN
2 A 1.0 10.0
3 A NaN NaN
4 B NaN NaN
5 B 2.0 20.0
6 B NaN 20.0
7 B NaN NaN
8 C NaN NaN
9 C NaN NaN
10 C NaN NaN
11 C NaN 30.0
我希望它变成:
A B C
0 A 0 0
1 A 0 0
2 A 1.0 10.0
3 A 1.0 10.0
4 B 0 0
5 B 2.0 20.0
6 B 2.0 20.0
7 B 2.0 20.0
8 C NaN 0
9 C NaN 0
10 C NaN 0
11 C NaN 30.0
我尝试使用 df.groupby('A').nth(1)
获取第一个元素并有条件地继续,但是 groupby
创建的新索引不是原始索引(即 0,4,8),无论如何我是否通过 .reset_index()
选项。
数据框重建代码:
df = pd.DataFrame({'A' : ["A", "A", "A", "A",
"B", "B", "B", "B","C", "C", "C", "C"],
'B' : [np.nan, np.nan, 1, np.nan,
np.nan, 2, np.nan, np.nan,
np.nan, np.nan, np.nan, np.nan],
'C' : [np.nan, np.nan, 10, np.nan,
np.nan, 20, 20, np.nan,
np.nan, np.nan, np.nan, 30]})
一个可能的想法是在 A
上使用 DataFrame.groupby
,然后使用自定义转换器函数:
def fx(s):
if s.isna().all():
return s
elif pd.isna(s.iloc[0]):
s.iloc[0] = 0
s = s.ffill().bfill()
return s
df[['B', 'C']] = df.groupby('A')[['B', 'C']].transform(fx)
# print(df)
A B C
0 A 0.0 0.0
1 A 0.0 0.0
2 A 1.0 10.0
3 A 1.0 10.0
4 B 0.0 0.0
5 B 2.0 20.0
6 B 2.0 20.0
7 B 2.0 20.0
8 C NaN 0.0
9 C NaN 0.0
10 C NaN 0.0
11 C NaN 30.0