【问题标题】:Python pandas replace NaN values of one column(A) by mode (of same column -A) with respect to another column in pandas dataframePython pandas 通过模式(同一列-A)相对于 pandas 数据框中的另一列替换一列(A)的 NaN 值
【发布时间】:2021-09-23 02:02:57
【问题描述】:

这是带有一些 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

我想将 'Number' 列的 NaN 值替换为相对于 'Street' 列的同一列的模式。。 p>

我需要的输出是:

    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

解释:

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

【问题讨论】:

    标签: python pandas dataframe replace nan


    【解决方案1】:

    也许更简单一点,因为mode 返回一个数组所以,您可以通过抓取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的另一个solution here

    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])))
    

    【讨论】:

    • 是的,我的第二个解决方案 transform 更改为 apply
    • @jezrael,真的..你是冠军。 +1 相同。
    【解决方案2】:

    使用 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/Nones,则可能出现错误:

    IndexError:索引 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-24
      • 1970-01-01
      • 1970-01-01
      • 2023-01-19
      • 2019-07-16
      • 2017-12-03
      • 1970-01-01
      相关资源
      最近更新 更多