如果 NaN 用另一列替换,Pandas 将组中的最后一项替换
Posted
技术标签:
【中文标题】如果 NaN 用另一列替换,Pandas 将组中的最后一项替换【英文标题】:Pandas replace last item in groupby if NaN with another colum 【发布时间】:2020-11-26 02:46:34 【问题描述】:我试图用另一列的值替换组中的最后一行,只有当它为空时。我可以分别完成这两部分,但似乎无法将它们结合起来。有人有什么想法吗?
这些是单独的部分:
# replace any NaN values with values from 'target'
df.loc[df['target'].isnull(),'target'] = df['value']
# replace last value in groupby with value from 'target'
df.loc[df.groupby('id').tail(1).index,'target'] = df['value']
原始数据:
date id value target
0 2020-08-07 id01 0.100775 NaN
1 2020-08-08 id01 0.215885 0.215885
2 2020-08-09 id01 0.012154 0.012154
3 2020-08-10 id01 0.374503 NaN
4 2020-08-07 id02 0.369707 0.369707
5 2020-08-08 id02 0.676743 0.676743
6 2020-08-09 id02 0.659521 0.659521
7 2020-08-10 id02 0.799071 NaN
将 groupby('id') 中最后一行的 'target' 列替换为 'value' 中的内容:
date id value target
0 2020-08-07 id01 0.100775 NaN
1 2020-08-08 id01 0.215885 0.215885
2 2020-08-09 id01 0.012154 0.012154
3 2020-08-10 id01 0.374503 0.374503
4 2020-08-07 id02 0.369707 0.369707
5 2020-08-08 id02 0.676743 0.676743
6 2020-08-09 id02 0.659521 0.659521
7 2020-08-10 id02 0.799071 0.799071
【问题讨论】:
【参考方案1】:使用 combine_first,您会被各种选择宠坏。
第一选择
将.groupby()
与nth(value)
一起使用
m=df.groupby('id',as_index=False).nth(-1).index#mask each last value in the group
df.loc[m, 'target'] = df['target'].combine_first(df['value'])populate value
第二个选项
使用combine_first
使用.iloc
访问器获取target
列和value
列中的最后一个值groupby
df.groupby('id').apply(lambda x:(x.iloc[-1:,3].combine_first(x.iloc[-1:,2])))\
.reset_index(level=0).combine_first(df)
第三个选项
选择每个组中的最后一个索引。根据需要填充列目标并使用 combine_first 更新 df
g=df.groupby('id').apply(lambda x:x.iloc[-1:]).reset_index(level=0, drop=True)
#df.loc[g, 'target'] = df['target'].combine_first(df['value'])
g.target=g.value
g.combine_first(df)
date id value target
0 2020-08-07 id01 0.100775 NaN
1 2020-08-08 id01 0.215885 0.215885
2 2020-08-09 id01 0.012154 0.012154
3 2020-08-10 id01 0.374503 0.374503
4 2020-08-07 id02 0.369707 0.369707
5 2020-08-08 id02 0.676743 0.676743
6 2020-08-09 id02 0.659521 0.659521
7 2020-08-10 id02 0.799071 0.799071
【讨论】:
@dingo 这有帮助吗?很高兴为您提供进一步的帮助【参考方案2】:在groupby()
中查找最后一个目标 的索引,然后使用.combine_first()
仅替换空值
indexes = df.groupby('id').tail(1).index
df.loc[indexes, 'target'] = df['target'].combine_first(df['value'])
#result
date id value target
0 2020-08-07 id01 0.100775 NaN
1 2020-08-08 id01 0.215885 0.215885
2 2020-08-09 id01 0.012154 0.012154
3 2020-08-10 id01 0.374503 0.374503
4 2020-08-07 id02 0.369707 0.369707
5 2020-08-08 id02 0.676743 0.676743
6 2020-08-09 id02 0.659521 0.659521
7 2020-08-10 id02 0.799071 0.799071
【讨论】:
【参考方案3】:fillna
在整个列上,但如果它不是每个“id”的最后一个缺失,则掩码回NaN
。
m = df['target'].isnull() & df['id'].duplicated(keep='last')
df['target'] = df['target'].fillna(df['value']).mask(m)
date id value target
0 2020-08-07 id01 0.100775 NaN
1 2020-08-08 id01 0.215885 0.215885
2 2020-08-09 id01 0.012154 0.012154
3 2020-08-10 id01 0.374503 0.374503
4 2020-08-07 id02 0.369707 0.369707
5 2020-08-08 id02 0.676743 0.676743
6 2020-08-09 id02 0.659521 0.659521
7 2020-08-10 id02 0.799071 0.799071
【讨论】:
【参考方案4】:这应该可以。添加了tail
变量只是为了便于阅读语法:
tail = df.groupby('id').tail(1)
df.loc[tail.index,'target'] = df.loc[tail.index]['target'].fillna(tail.value)
输出:
0 idx date id value target
1 0 2020-08-07 id01 0.100775 NaN
2 1 2020-08-08 id01 0.215885 0.215885
3 2 2020-08-09 id01 0.012154 0.012154
4 3 2020-08-10 id01 0.374503 0.374503
5 4 2020-08-07 id02 0.369707 0.369707
6 5 2020-08-08 id02 0.676743 0.676743
7 6 2020-08-09 id02 0.659521 0.659521
8 7 2020-08-10 id02 0.799071 0.799071
【讨论】:
以上是关于如果 NaN 用另一列替换,Pandas 将组中的最后一项替换的主要内容,如果未能解决你的问题,请参考以下文章
Power Query / Power BI - 用另一列中的值替换空值
Python Pandas 将一列中的 NaN 替换为第二列对应行的值