我有系统事件时间的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)
我尝试过上述不同的变化但无济于事。提前感谢您提供的任何帮助。
另外,如果我搞砸了问题,请随时告诉我。不确定我的头衔是否也很棒。
答案 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