我有一个如下所示的数据框
ID DATE PROFIT
2342 2017-03-01 457
2342 2017-06-01 658
2342 2017-09-01 3456
2342 2017-12-01 345
2342 2018-03-01 235
2342 2018-06-01 23
808 2016-12-01 200
808 2017-03-01 9346
808 2017-06-01 54
808 2017-09-01 314
808 2017-12-01 57
....
....
对于每个ID:
我想确定利润是否保持在200到1000之间。 我想以这样的方式进行操作:计数器(新列)指示连续有多少个季度(最新和之前)满足此条件。如果由于某种原因,中间四分之一之一不符合条件,则计数器应重置。
所以输出应类似于:
ID DATE PROFIT COUNTER
2342 2017-03-01 457 1
2342 2017-06-01 658 2
2342 2017-09-01 3456 0
2342 2017-12-01 345 1
2342 2018-03-01 235 2
2342 2018-06-01 23 0
808 2016-12-01 200 1
808 2017-03-01 9346 0
808 2017-06-01 54 0
808 2017-09-01 314 1
808 2017-12-01 57 0
....
....
我正在考虑使用shift功能访问/访问前几行的条件,但是,如果有更好的方法来检查datetime值中的条件,将是一个很好的了解。
答案 0 :(得分:3)
IIUC通过使用cumsum
创建帮助键,然后我们只需要过滤一下,然后分配回去的fillna
,而不是200到1000之间的0
s=(~df.PROFIT.between(200,1000)).groupby(df['ID']).cumsum()
df['COUNTER']=df[df.PROFIT.between(200,1000)].groupby([df.ID,s]).cumcount()+1
df.COUNTER.fillna(0,inplace=True)
df
Out[226]:
ID DATE PROFIT COUNTER
0 2342 2017-03-01 457 1.0
1 2342 2017-06-01 658 2.0
2 2342 2017-09-01 3456 0.0
3 2342 2017-12-01 345 1.0
4 2342 2018-03-01 235 2.0
5 2342 2018-06-01 23 0.0
6 808 2016-12-01 200 1.0
7 808 2017-03-01 9346 0.0
8 808 2017-06-01 54 0.0
9 808 2017-09-01 314 1.0
10 808 2017-12-01 57 0.0
答案 1 :(得分:2)
设置一个满足条件的值1的条件列,然后进行分组和求和。
df['criteria'] = 0
df.loc[(df['PROFIT'] >= 200) & (df['PROFIT'] <= 1000), 'criteria'] = 1
df['result'] = df.groupby(['ID', df.criteria.eq(0).cumsum()])['criteria'].cumsum()
ID DATE PROFIT criteria result
0 2342 2017-03-01 457 1 1
1 2342 2017-06-01 658 1 2
2 2342 2017-09-01 3456 0 0
3 2342 2017-12-01 345 1 1
4 2342 2018-03-01 235 1 2
5 2342 2018-06-01 23 0 0
6 808 2016-12-01 200 1 1
7 808 2017-03-01 9346 0 0
8 808 2017-06-01 54 0 0
9 808 2017-09-01 314 1 1
10 808 2017-12-01 57 0 0
答案 2 :(得分:0)
将groupby
与cumsum
和cumcount
结合使用,然后简单地使用loc
来获取第一行并根据需要进行排列:
df['BOOL'] = (~df['PROFIT'].between(200, 1000)).cumsum()
df['COUNTER'] = df.groupby('BOOL', 'ID']).cumcount()
df.loc[df.groupby('ID', as_index=False)['BOOL'].apply(lambda x: x.loc[:x.idxmin()-1]).index.levels[1], 'COUNTER'] += 1
现在:
print(df)
是:
ID DATE PROFIT COUNTER
0 2342 2017-03-01 457 1
1 2342 2017-06-01 658 2
2 2342 2017-09-01 3456 0
3 2342 2017-12-01 345 1
4 2342 2018-03-01 235 2
5 2342 2018-06-01 23 0
6 808 2016-12-01 200 1
7 808 2017-03-01 9346 0
8 808 2017-06-01 54 0
9 808 2017-09-01 314 1
10 808 2017-12-01 57 0
如您所期望的输出中所示。
答案 3 :(得分:0)
def magic(y):
return y * (y.groupby((y != y.shift()).cumsum()).cumcount() + 1)
data["condition"] = data['PROFIT'].between(200, 1000)
data["COUNTER"] = data.groupby("ID").condition.apply(magic)
ID DATE PROFIT condition COUNTER
0 2342 2017-03-01 457 True 1
1 2342 2017-06-01 658 True 2
2 2342 2017-09-01 3456 False 0
3 2342 2017-12-01 345 True 1
4 2342 2018-03-01 235 True 2
5 2342 2018-06-01 23 False 0
6 808 2016-12-01 200 True 1
7 808 2017-03-01 9346 False 0
8 808 2017-06-01 54 False 0
9 808 2017-09-01 314 True 1
10 808 2017-12-01 57 False 0
答案 4 :(得分:-1)
会不会像以下工作那么简单?
int strlen(char* str)
{
int i = 0;
while (*str != '\0')
{
i++;
str++;
}
return i;
}
int main()
{
char line[1];
char* v = line;
char* s = new char[1];
cout << "for s " << strlen(s) << endl;
cout << "for v " << strlen(v) << endl;
}