Pandas满足条件就填组
Pandas fill in group if condition is met
我有一个 DataFrame,我希望在其中根据分组在列中填充值。如果要填充的列中只有一个唯一值,我只想填充值(通过使用 ffill
和 bfill
传播非 NaN 值);否则,它应该保持原样。我下面的代码有一个示例数据集,我尝试在其中执行此操作,但出现错误。
代码:
df = pd.DataFrame({"A": [1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, 6],
"B": ['a', 'a', np.nan, 'b', 'b', 'c', np.nan, 'd', np.nan, 'e', 'e', np.nan, 'h', 'h'],
"C": [5.0, np.nan, 4.0, 4.0, np.nan, 9.0, np.nan, np.nan, 9.0, 8.0, np.nan, 2.0, np.nan, np.nan]})
col_to_groupby = "A"
col_to_modify = "B"
group = df.groupby(col_to_groupby)
modified = group[group[col_to_modify].nunique() == 1].transform(lambda x: x.ffill().bfill())
df.update(modified)
错误:
KeyError: 'Columns not found: False, True'
原始数据集:
A B C
0 1 a 5.0
1 1 a NaN
2 2 NaN 4.0
3 2 b 4.0
4 2 b NaN
5 3 c 9.0
6 3 NaN NaN
7 3 d NaN
8 3 NaN 9.0
9 4 e 8.0
10 4 e NaN
11 5 NaN 2.0
12 6 h NaN
13 6 NaN NaN
想要的结果:
A B C
0 1 a 5.0
1 1 a NaN
2 2 b 4.0
3 2 b 4.0
4 2 b NaN
5 3 c 9.0
6 3 NaN NaN
7 3 d NaN
8 3 NaN 9.0
9 4 e 8.0
10 4 e NaN
11 5 NaN 2.0
12 6 h NaN
13 6 h NaN
以上是想要的结果,因为
- 行索引 2 在组 2 中,它在 B 列(“b”)中只有 1 个唯一值,因此已更改。
- 行索引 6 和 8 在第 3 组中,但 B 列中有 2 个唯一值(“c”和“d”),因此它们未更改。
- 行索引 5 在组 11 中,但 B 列中没有要传播的数据。
- 行索引 13 在第 6 组中,它在 B 列(“h”)中只有 1 个唯一值,因此已更改。
一个选项是在 groupby.apply
中添加条件:
df[col_to_modify] = df.groupby(col_to_groupby)[col_to_modify].apply(lambda x: x.ffill().bfill() if x.nunique()==1 else x)
另一种可能是使用 groupby
+ transform(nunique)
+ eq
为具有唯一值的组创建布尔过滤器;然后使用 groupby
+ first
更新这些行(first
删除 NaN)使用 where
:
g = df.groupby(col_to_groupby)[col_to_modify]
df[col_to_modify] = g.transform('first').where(g.transform('nunique').eq(1), df[col_to_modify])
输出:
A B C
0 1 a 5.0
1 1 a NaN
2 2 b 4.0
3 2 b 4.0
4 2 b NaN
5 3 c 9.0
6 3 NaN NaN
7 3 d NaN
8 3 NaN 9.0
9 4 e 8.0
10 4 e NaN
11 5 NaN 2.0
12 6 h NaN
13 6 h NaN
我有一个 DataFrame,我希望在其中根据分组在列中填充值。如果要填充的列中只有一个唯一值,我只想填充值(通过使用 ffill
和 bfill
传播非 NaN 值);否则,它应该保持原样。我下面的代码有一个示例数据集,我尝试在其中执行此操作,但出现错误。
代码:
df = pd.DataFrame({"A": [1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6, 6],
"B": ['a', 'a', np.nan, 'b', 'b', 'c', np.nan, 'd', np.nan, 'e', 'e', np.nan, 'h', 'h'],
"C": [5.0, np.nan, 4.0, 4.0, np.nan, 9.0, np.nan, np.nan, 9.0, 8.0, np.nan, 2.0, np.nan, np.nan]})
col_to_groupby = "A"
col_to_modify = "B"
group = df.groupby(col_to_groupby)
modified = group[group[col_to_modify].nunique() == 1].transform(lambda x: x.ffill().bfill())
df.update(modified)
错误:
KeyError: 'Columns not found: False, True'
原始数据集:
A B C
0 1 a 5.0
1 1 a NaN
2 2 NaN 4.0
3 2 b 4.0
4 2 b NaN
5 3 c 9.0
6 3 NaN NaN
7 3 d NaN
8 3 NaN 9.0
9 4 e 8.0
10 4 e NaN
11 5 NaN 2.0
12 6 h NaN
13 6 NaN NaN
想要的结果:
A B C
0 1 a 5.0
1 1 a NaN
2 2 b 4.0
3 2 b 4.0
4 2 b NaN
5 3 c 9.0
6 3 NaN NaN
7 3 d NaN
8 3 NaN 9.0
9 4 e 8.0
10 4 e NaN
11 5 NaN 2.0
12 6 h NaN
13 6 h NaN
以上是想要的结果,因为
- 行索引 2 在组 2 中,它在 B 列(“b”)中只有 1 个唯一值,因此已更改。
- 行索引 6 和 8 在第 3 组中,但 B 列中有 2 个唯一值(“c”和“d”),因此它们未更改。
- 行索引 5 在组 11 中,但 B 列中没有要传播的数据。
- 行索引 13 在第 6 组中,它在 B 列(“h”)中只有 1 个唯一值,因此已更改。
一个选项是在 groupby.apply
中添加条件:
df[col_to_modify] = df.groupby(col_to_groupby)[col_to_modify].apply(lambda x: x.ffill().bfill() if x.nunique()==1 else x)
另一种可能是使用 groupby
+ transform(nunique)
+ eq
为具有唯一值的组创建布尔过滤器;然后使用 groupby
+ first
更新这些行(first
删除 NaN)使用 where
:
g = df.groupby(col_to_groupby)[col_to_modify]
df[col_to_modify] = g.transform('first').where(g.transform('nunique').eq(1), df[col_to_modify])
输出:
A B C
0 1 a 5.0
1 1 a NaN
2 2 b 4.0
3 2 b 4.0
4 2 b NaN
5 3 c 9.0
6 3 NaN NaN
7 3 d NaN
8 3 NaN 9.0
9 4 e 8.0
10 4 e NaN
11 5 NaN 2.0
12 6 h NaN
13 6 h NaN