如何将函数应用于数据框列以创建迭代列

时间:2017-11-07 09:12:32

标签: python-3.x pandas

我有系统事件时间的ID,我已经按id(单个系统)对事件时间进行了分组,并且如果eventtimes.diff()大于1天,则创建一个新列,其中值为1,否则为0。现在我有了标志,我试图创建一个将应用于groupby('ID')的函数,所以新列以1开头,并为新列中的每一行保持返回1,直到标志显示1然后新列将从1上升到2并继续返回2,直到该标志再次显示1。

我将这与groupby('ID')一起应用,因为我需要新列重新开始,每个ID为1。

我尝试了以下内容:

def try(x):
    y = 1
    if row['flag']==0:
        y = y
    else:
        y += y+1 

df['NewCol'] = df.groupby('ID')['flag'].apply(try)

我尝试过上述不同的变化但无济于事。提前感谢您提供的任何帮助。

另外,如果我搞砸了问题,请随时告诉我。不确定我的头衔是否也很棒。

1 个答案:

答案 0 :(得分:0)

使用boolean indexing过滤+ cumcount + reindex什么是更快的解决方案loopy apply

我认为每个群组只需要1,如果没有1则会将1添加到输出中:

df = pd.DataFrame({
    'ID': ['a','a','a','a','b','b','b','b','b'],
    'flag': [0,0,1,1,0,0,1,1,1]
})


df['new'] = (df[df['flag'] == 1].groupby('ID')['flag']
                                .cumcount()
                                .add(1)
                                .reindex(df.index, fill_value=1))
print (df)
  ID  flag  new
0  a     0    1
1  a     0    1
2  a     1    1
3  a     1    2
4  b     0    1
5  b     0    1
6  b     1    1
7  b     1    2
8  b     1    3

详情:

#filter by condition
print (df[df['flag'] == 1])
  ID  flag
2  a     1
3  a     1
6  b     1
7  b     1
8  b     1

#count per group
print (df[df['flag'] == 1].groupby('ID')['flag'].cumcount())
2    0
3    1
6    0
7    1
8    2
dtype: int64

#add 1 for count from 1
print (df[df['flag'] == 1].groupby('ID')['flag'].cumcount().add(1))
2    1
3    2
6    1
7    2
8    3
dtype: int64

如果需要计算0且未添加0 -1

df['new'] = (df[df['flag'] == 0].groupby('ID')['flag']
                                .cumcount()
                                .add(1)
                                .reindex(df.index, fill_value=-1))
print (df)
  ID  flag  new
0  a     0    1
1  a     0    2
2  a     1   -1
3  a     1   -1
4  b     0    1
5  b     0    2
6  b     1   -1
7  b     1   -1
8  b     1   -1

另外两步解决方案:

df['new'] = df[df['flag'] == 1].groupby('ID')['flag'].cumcount().add(1)
df['new'] = df['new'].fillna(1).astype(int)
print (df)
  ID  flag  new
0  a     0    1
1  a     0    1
2  a     1    1
3  a     1    2
4  b     0    1
5  b     0    1
6  b     1    1
7  b     1    2
8  b     1    3