【问题标题】:pandas Dataframe Replace NaN values with with previous value based on a key columnpandas Dataframe 根据键列将 NaN 值替换为先前的值
【发布时间】:2018-12-05 13:19:30
【问题描述】:

我有一个如下所示的 pd.dataframe:

key_value    a    b    c    d    e
value_01     1    10   x   NaN  NaN
value_01    NaN   12  NaN  NaN  NaN
value_01    NaN   7   NaN  NaN  NaN
value_02     7    4    y   NaN  NaN 
value_02    NaN   5   NaN  NaN  NaN
value_02    NaN   6   NaN  NaN  NaN
value_03     19   15   z   NaN  NaN

所以现在基于key_value,

对于“a”和“c”列,我想根据 key_value 从同一列“a”和“c”复制最后一个单元格的值。

对于另一列“d”,我想将“i - 1”行的单元格值从“b”列复制到“d”列第 i 个单元格。

最后,对于“e”列,我想将“i - 1”个单元格的总和从“b”列复制到“e”列第 i 个单元格。

对于每个 key_value,列 'a'、'b' 和 'c' 在它们的第一行中都有一些值,根据这些值复制下一个值或对于不同列的值正在生成。

key_value    a    b    c    d    e
value_01     1    10   x   NaN  NaN
value_01     1    12   x    10   10
value_01     1    7    x    12   22
value_02     7    4    y   NaN  NaN
value_02     7    5    y    4    4
value_02     7    6    y    5    9
value_03     8    15   z   NaN  NaN

我目前的做法:

size = df.key_value.size
for i in range(size):
    if pd.isna(df.a[i]) and df.key_value[i] == output.key_value[i - 1]:
        df.a[i] = df.a[i - 1]
        df.c[i] = df.c[i - 1]
        df.d[i] = df.b[i - 1]
        df.e[i] = df.e[i] + df.b[i - 1]

对于像 'a' 和 'b' 这样的列,NaN 值都在相同的行索引中。

我的方法有效,但需要很长时间,因为我的 datframe 有超过 50000 条记录,我想知道是否有不同的方法可以做到这一点,因为我有多个列,如 'a' 和 'b' 需要复制值基于 'key_value' 和一些列,这些列使用诸如 'b' 之类的列来计算值

【问题讨论】:

    标签: python pandas dataframe pandas-groupby


    【解决方案1】:

    pd.concatgroupbyassign

    pd.concat([
        g.ffill().assign(d=lambda d: d.b.shift(), e=lambda d: d.d.cumsum())
        for _, g in df.groupby('key_value')
    ])
    
      key_value     a  b  c    d    e
    0  value_01   1.0  1  x  NaN  NaN
    1  value_01   1.0  2  x  1.0  1.0
    2  value_01   1.0  3  x  2.0  3.0
    3  value_02   7.0  4  y  NaN  NaN
    4  value_02   7.0  5  y  4.0  4.0
    5  value_02   7.0  6  y  5.0  9.0
    6  value_03  19.0  7  z  NaN  NaN
    

    groupbyapply

    def h(g):
        return g.ffill().assign(
            d=lambda d: d.b.shift(), e=lambda d: d.d.cumsum())
    
    df.groupby('key_value', as_index=False, group_keys=False).apply(h)
    

    【讨论】:

    • 我在列 'd' 和 'e 也应该根据 key_value 进行调整的问题中犯了一个错误。感谢您的帮助。
    • 我忘了问一列说列'f',我只需要从上一个单元格值+1,我应该怎么做。再次感谢您的回答。
    • 从哪一列的上一个单元格值中添加一个?
    • 这是我在原始问题中忘记询问的另一列,它仍然取决于键值。因此,如果第一个值为 1,则同一列中的下一个单元格应该有 2,之后的一个单元格应该有 3。这就像 ffill() 但有 +1。
    • 所以一个名为f 的列引用了它自己?你看到我的问题了吗?如果 i == 3 处 f 列的单元格值应该是 1 加上 i == 2 处 f 列的单元格值?
    【解决方案2】:

    您可以使用groupby + ffill 进行分组填充。其他操作需要shiftcumsum

    一般来说,请注意,许多常见操作已在 Pandas 中高效实现。

    g = df.groupby('key_value')
    
    df['a'] = g['a'].ffill()
    df['c'] = g['c'].ffill()
    df['d'] = df['b'].shift()
    df['e'] = df['d'].cumsum()
    
    print(df)
    
      key_value     a  b  c    d     e
    0  value_01   1.0  1  x  NaN   NaN
    1  value_01   1.0  2  x  1.0   1.0
    2  value_01   1.0  3  x  2.0   3.0
    3  value_02   7.0  4  y  3.0   6.0
    4  value_02   7.0  5  y  4.0  10.0
    5  value_02   7.0  6  y  5.0  15.0
    6  value_03  19.0  7  z  6.0  21.0
    

    【讨论】:

    • 感谢您的帮助,这很有帮助,我在“d”列和“e”列也应该根据 key_value 进行调整的问题中犯了一个错误。
    • 我刚刚为他们将 df 更改为 g 并且它可以工作。现在只需要验证。再次感谢。
    • @user9996043,没问题,别忘了给accept一个有帮助的答案:)
    • 我忘了问一列说列f,我只需要从上一个单元格值中+1,列f指的是它自己,所以如果在列@ 987654330@ i==1 的值是 1 i==2 中的值应该变成 2 以前是 NaN
    猜你喜欢
    • 1970-01-01
    • 2023-01-19
    • 2017-07-04
    • 1970-01-01
    • 2020-05-21
    • 2018-11-14
    • 2013-09-12
    相关资源
    最近更新 更多