【问题标题】:Replacing NaN values in a DataFrame row with values from other rows based on a (non-unique) column value将 DataFrame 行中的 NaN 值替换为基于(非唯一)列值的其他行中的值
【发布时间】:2020-11-03 00:16:38
【问题描述】:

我有一个类似于以下的 DataFrame,其中我有一列具有非唯一值(在本例中为地址)以及包含有关它的信息的其他一些列。

df = pd.DataFrame({'address': {0:'11 Star Street', 1:'22 Milky Way', 2:'88 Dark Drive', 3:'33 Planet Place', 4:'22 Milky Way', 5:'22 Milky Way'}, 'val': {0:10, 1:'', 2:'', 3:20, 4: 20, 5:''}, 'val2': {0:20, 1:'', 2:'', 3:40, 4:10, 5:''}})

           address val val2
0   11 Star Street  10   20
1     22 Milky Way         
2    88 Dark Drive         
3  33 Planet Place  20   40
4     22 Milky Way  20   10
5     22 Milky Way          

有些地址在 DataFrame 中出现了不止一次,而其中一些重复的地址缺少信息。如果某行缺少值,但该地址出现在 DataFrame 的另一行中,我想将 NaN 值替换为来自同一地址的值以获得如下结果:

           address val val2
0   11 Star Street  10   20
1     22 Milky Way  20   10
2    88 Dark Drive         
3  33 Planet Place  20   40
4     22 Milky Way  20   10
5     22 Milky Way  20   10

使用字典之类的东西是不可行的,因为 DataFrame 包含数千个不同的地址。

编辑:可以安全地假设两个值都丢失或两者都存在。换句话说,永远不会有只有 val 而不是 val2 的行,反之亦然。但是,可以将这种可能的情况考虑在内的答案会更好!

【问题讨论】:

    标签: python pandas numpy dataframe


    【解决方案1】:

    您可以通过多种方式执行此操作,最简单的是 groupby 和 ffill / bfill 组。

    import numpy as np
    import pandas as pd
    df = df.replace('',np.nan,regex=True).groupby('address').apply(lambda x : x.ffill().bfill())
    
    print(df)
    
               address   val  val2
    0   11 Star Street  10.0  20.0
    1     22 Milky Way  20.0  10.0
    2    88 Dark Drive   NaN   NaN
    3  33 Planet Place  20.0  40.0
    4     22 Milky Way  20.0  10.0
    5     22 Milky Way  20.0  10.0
    

    另一种更高效的方法是沿您的轴使用update

    vals = df.replace('',np.nan,regex=True).groupby('address').first()
    
    print(vals)
        
                         val  val2
        address                    
        11 Star Street   10.0  20.0
        22 Milky Way     20.0  10.0
        33 Planet Place  20.0  40.0
        88 Dark Drive     NaN   NaN
    
    df = df.set_index('address')
    
    df.update(vals)
    
                    val val2
    address                 
    11 Star Street   10   20
    22 Milky Way     20   10
    88 Dark Drive           
    33 Planet Place  20   40
    22 Milky Way     20   10
    22 Milky Way     20   10
    

    【讨论】:

    • 很好的解决方案,有没有办法使用 groupby 并仅在 val 和 val2 上填充 bfill?例如,如果我在 DataFrame 中有其他列可能有 NaN 但我不想覆盖。
    • @shaye059,是的,您可以有条件地选择您的列,即 vals = df.replace('',np.nan,regex=True).groupby('address')[['val','val2']].first() 然后 df.set_index('address');df.update(vals)df.replace('',np.nan,regex=True).groupby('address')[['val','val2']].apply(lambda x : x.ffill().bfill())
    猜你喜欢
    • 1970-01-01
    • 2023-03-03
    • 2013-01-13
    • 1970-01-01
    • 2020-11-07
    • 1970-01-01
    • 2023-01-19
    • 1970-01-01
    • 2022-11-29
    相关资源
    最近更新 更多