如果 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 替换为第二列对应行的值

用 pandas 数据框中另一列的值填充多列中的 Na

pandas:用列中的最后一个非 NaN 值替换 NaN [重复]

有效地将值从一列替换到另一列 Pandas DataFrame