Python pandas:在groupby对象中替换选定值

1 投票
1 回答
1872 浏览
提问于 2025-04-20 02:44

我有一个很大的数据表,里面有四列个人信息:一个人 ID 号码、年份、年龄和搬家状态。我使用 groupby 方法根据个人 ID 号码(存储在 unique_pid2 列中)来分组。

import pandas as pd 

gr_data = pd.read_csv("M:/test.csv").groupby('unique_pid2')

group = gr_data.get_group('5904_181')

print group

每个组看起来是这样的:

       unique_pid2  year  age  moved
798908    5904_181  1983    0      0
798909    5904_181  1984    0      0
798910    5904_181  1985    0      0
798911    5904_181  1986    0      0
798912    5904_181  1987    2      5
798913    5904_181  1988    0      5
798914    5904_181  1989    0      0
798915    5904_181  1990    0      0
798916    5904_181  1991    0      0
798917    5904_181  1992    0      0
798918    5904_181  1993    0      0
798928    5904_181  2009   24      5
798929    5904_181  2011   26      1

对于每个组,我想把 movedage 列中等于零的值填上其他的值,但只有在这些零值的观察数据被至少一个非零值的观察数据“夹住”的情况下,也就是说,前后都有非零的值。

比如,在上面的组中,我想填充 798914: 798918 这几行,但不想填充 798908:798911。对于那些 agemoved 值都是 0 的观察数据,我已经写了一个函数来相应地替换这些零值。但我想在“夹住”的情况下,比如 798914: 798918,调用这个函数,但我不知道怎么找到这些行。

到目前为止,我尝试了类似这样的代码:

group.loc[(group["age"] == 0) & (group["moved"] == 0), ['age', 'moved']] = someFunction(group)

但是这填充了那些没有被夹住的观察数据,比如上面组的前四行。我该如何处理,才能在每个组中只对那些被夹住的观察数据应用这个函数,填充 agemoved 值为 0 的情况,而这些观察数据的前后都有非零值呢?

1 个回答

1

假设agemoved的值都是非负的,你可以用cumsum来选择你想要的行:

mask = ((grp['age'].cumsum()>0) & (grp['moved'].cumsum()>0)
        & (grp['age'] == 0) & (grp['moved'] == 0))

因为当累计和大于0时,之前一定有一个正值。

举个例子,

import pandas as pd

df = pd.read_csv("M:/test.csv")
gr_data = df.groupby('unique_pid2')
def foo(grp):
    mask = ((grp['age'].cumsum()>0) & (grp['moved'].cumsum()>0)
            & (grp['age'] == 0) & (grp['moved'] == 0))
    grp.loc[mask, ['age', 'moved']] = 'foo'
    return grp
df = gr_data.apply(foo)
print(df)

会得到

   unique_pid2  year  age moved
0     5904_181  1983    0     0
1     5904_181  1984    0     0
2     5904_181  1985    0     0
3     5904_181  1986    0     0
4     5904_181  1987    2     5
5     5904_181  1988    0     5
6     5904_181  1989  foo   foo
7     5904_181  1990  foo   foo
8     5904_181  1991  foo   foo
9     5904_181  1992  foo   foo
10    5904_181  1993  foo   foo
11    5904_181  2009   24     5
12    5904_181  2011   26     1

撰写回答