使用 pandas 数据框,基于关键列用前一个值替换 NaN 值。

3

I have a pd.dataframe that looks like this:

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'个单元格中的值从列'b'复制到列'd'中的第'i-1'个单元格。

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

对于每个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 值都在同一行索引中。
我的方法可行,但是因为我的数据框记录超过了50000条,所以处理时间很长,我想知道是否有另一种不同的方法来做到这一点,因为我有多个类似于'a'和'b'的列,需要基于 'key_value' 复制值,并且一些列的值是使用诸如 'b' 列之类的列进行计算的。
2个回答

3

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

groupby and apply

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'也应根据关键值进行调整。感谢您的帮助。 - user9996043
在哪一列中将前一个单元格的值加1? - piRSquared
这是我在原问题中忘记询问的另一列,它仍然依赖于关键值。因此,如果第一个值为1,则同一列中的下一个单元格应为2,再下一个单元格为3。就像ffill()一样,但加上了+1。 - user9996043
一个指向自身的名为 f 的列?你看到我的问题了吗?如果在 i == 3 时,列 f 的单元格值应该是列 f 在 i == 2 时的单元格值加1? - piRSquared
据我理解,def h(g): 目前正在对除 assign 中指定的列以外的所有列执行 ffill() 操作,那么我该如何排除某些列使其不受任何操作影响呢? - user9996043
显示剩余6条评论

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进行调整。 - user9996043
1
我只是为他们把“df”改成了“g”,现在可以工作了。现在只需要验证一下。再次感谢。 - user9996043
@user9996043,没问题,别忘了接受帮助过你的答案 :) - jpp
我忘了询问关于第1列的问题,即列“f”,在这一列中,我只需要从前一个单元格的值加1,列“f”是指向自身的,因此如果在列“f”中,在i==1时值为1,则在i==2时的值应该变为2,而之前的值为NaN。 - user9996043

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接