繁体   English   中英

Python pandas 用模式(同一列 -A)相对于 Pandas 数据帧中的另一列替换一列(A)的 NaN 值

[英]Python pandas replace NaN values of one column(A) by mode (of same column -A) with respect to another column in pandas dataframe

这是带有一些NaN值的数据框,

data = {'Number':[100,None,None,200,150,None,100,120,110,210,120],
    'Street':['A','B','C','D','C','D','A','B','B','D','B']}
df =pd.DataFrame(data)
df

输出:

    Number  Street
0   100.0   A
1   NaN     B
2   NaN     C
3   200.0   D
4   150.0   C
5   NaN     D
6   100.0   A
7   120.0   B
8   110.0   B
9   210.0   D
10  120.0   B

我想用与列'Street' 相关的同一列的模式替换列'Number'NaN值。

我需要的输出是:

    Number  Street
0   100       A
1   120       B
2   150       C
3   200       D
4   150       C
5   200       D
6   100       A
7   120       B
8   110       B
9   210       D
10  120       B

解释:

例如,考虑第 1 行,它在Number列中有一个NaN值,对应的StreetB NumberNaN值应替换为120.0 ,这是Number列相对于Street 的模式 因为,街道B Number列的其他值是120.0, 110.0120.0 (查看第 7、8、10 行),并且其模式为120.0

使用GroupBy.transform和 lambda 函数返回优先mode并用Series.fillna替换缺失值:

f = lambda x: x.mode().iat[0]
df['Number'] = df['Number'].fillna(df.groupby('Street')['Number'].transform(f))

或者:

f = lambda x: fillna(x.mode().iat[0])
df['Number'] = df.groupby('Street')['Number'].transform(f)

print (df)
    Number Street
0    100.0      A
1    120.0      B
2    150.0      C
3    200.0      D
4    150.0      C
5    200.0      D
6    100.0      A
7    120.0      B
8    110.0      B
9    210.0      D
10   120.0      B

如果某些组只有NaN/None s,则可能出现错误:

索引错误:索引 0 超出轴 0 的范围,大小为 0

那么解决办法是:

data = {'Number':[None,None,None,200,150,None,None,120,110,210,120],
    'Street':['A','B','C','D','C','D','A','B','B','D','B']}
df =pd.DataFrame(data)
print (df)
    Number Street
0      NaN      A
1      NaN      B
2      NaN      C
3    200.0      D
4    150.0      C
5      NaN      D
6      NaN      A
7    120.0      B
8    110.0      B
9    210.0      D
10   120.0      B

f = lambda x: x.mode().iat[0] if x.notna().any() else np.nan
df['Number'] = df['Number'].fillna(df.groupby('Street')['Number'].transform(f))
print (df)
    Number Street
0      NaN      A
1    120.0      B
2    150.0      C
3    200.0      D
4    150.0      C
5    200.0      D
6      NaN      A
7    120.0      B
8    110.0      B
9    210.0      D
10   120.0      B

也许更简单一点,因为mode返回一个数组所以,您可以通过获取Number的第一个元素来估算Number的 Nan 值以获得结果。

解决方案1:

>>> df['Number'] = df.groupby('Street')['Number'].apply(lambda x: x.fillna(x.mode()[0]))
    # df['Number'] = df.groupby('Street').transform(lambda x: x.fillna(x.mode()[0]))
>>> df
    Number Street
0    100.0      A
1    120.0      B
2    150.0      C
3    200.0      D
4    150.0      C
5    200.0      D
6    100.0      A
7    120.0      B
8    110.0      B
9    210.0      D
10   120.0      B

解决方案2:

您可以在此处查看基于locfirst_valid_index的另一个解决方案

df['Number'] = df.groupby('Street')['Number'].transform(lambda s: s.loc[s.first_valid_index()])

或者

df.assign(Number=df.groupby(['Street']).Number.apply(lambda x: x.fillna(x.mode()[0])))

  or

df.assign(Number=df.groupby(['Street']).transform(lambda x: x.fillna(x.mode()[0])))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM