根据其他行的条件填充数据框的行

时间:2021-02-10 10:11:18

标签: python pandas dataframe

我有一个这样的数据框:

pd.DataFrame({"ID1": ["A", "B", "C", "A", "C", "C", "A"],
              "ID2": ["a", "b", "c", "a", "e", "c", "b"],
              "Month": [1, 4, 7, 4, 2, 9, 3],
              "Value": [10, 20, 40, 60, 20, 30, 10]})
ID1 ID2  Month  Value
A   a      1     10
B   b      4     20
C   c      7     40
A   a      4     60
C   e      2     20
C   c      9     30
A   b      3     10

我想用“ID1”+“ID2”-组合的前一个月的值来填充缺失月份的值,即:组合“A”的第2个月和第3个月没有值"+"a",所以它应该取第 1 个月的值。在第 4 个月,我们有一个 "A"+"a" 的值,所以应该取这个值,直到有一个月的另一个值。

对于组合“C”+“c”,值应该从第 7 个月开始出现,因为它是组合出现的第一个值。

结束数据框应该是这样的:

ID1 ID2  Month  Value
A   a      1     10
A   a      2     10
A   a      3     10
A   a      4     60
A   a      5     60
A   a      6     60
A   a      7     60
A   a      8     60
A   a      9     60
A   a      10    60
A   a      11    60
A   a      12    60
B   b      4     20
C   c      1     0
C   c      2     0
C   c      3     0
C   c      4     0
C   c      5     0
C   c      6     0
C   c      7     40
C   c      8     40
C   c      9     30
C   c      10    30
C   c      11    30
C   c      12    30
... ...    ...   ...

我开始我的方法有点低效(我猜):

  1. 循环 1:12

  2. 循环“ID1”+“ID2”的唯一组合

  3. 如果存在“ID1”+“ID2”和月份的行

    然后去下个月

  4. 再看“ID1”+“ID2”组合的前一个月

    如果值存在

    然后取值

    否则将值设为 0

有没有更好的方法来做到这一点,或者有一个包可以帮助我有效地计算?

1 个答案:

答案 0 :(得分:1)

定义如下函数来处理每组:

def proc(grp):
    wrk = grp.set_index('Month').Value.reindex(np.arange(1, 13).tolist())\
        .ffill().fillna(0, downcast='infer')
    id1, id2 = grp.iloc[0, :2].tolist()
    wrk.index = pd.MultiIndex.from_product([[id1], [id2], wrk.index],
        names=['ID1', 'ID2', 'Month'])
    return wrk

然后,为了获得预期的结果,将 dfID1ID2 和 应用以上函数:

result = df.groupby(['ID1', 'ID2'], group_keys=False).apply(proc).reset_index()

最后一步是 reset_index() 转换结果(连接) 串联成一个 DataFrame。

('A', 'a')('C', 'c') 组的结果片段是:

   ID1 ID2  Month  Value
0    A   a      1     10
1    A   a      2     10
2    A   a      3     10
3    A   a      4     60
4    A   a      5     60
5    A   a      6     60
6    A   a      7     60
7    A   a      8     60
8    A   a      9     60
9    A   a     10     60
10   A   a     11     60
11   A   a     12     60
...
36   C   c      1      0
37   C   c      2      0
38   C   c      3      0
39   C   c      4      0
40   C   c      5      0
41   C   c      6      0
42   C   c      7     40
43   C   c      8     40
44   C   c      9     30
45   C   c     10     30
46   C   c     11     30
47   C   c     12     30