以下是我拥有的数据框。 JourneyGroup
是我的预期专栏。
Day Journey InitialValue Value JourneyGroup
0 12 1 3.0 4 1
1 12 1 4.0 5 1
2 12 0 NaN 7 1
3 12 0 NaN 2 1
4 12 1 5.0 8 2
5 12 0 NaN 9 2
6 13 1 3.0 4 3
7 13 1 4.0 5 3
8 13 0 NaN 7 3
9 13 0 NaN 6 3
10 13 1 1.0 2 3
11 13 0 NaN 9 0
如果Journey == 1
,则表示旅程的开始。只要Journey
处于打开状态,其他Journey
就不能在随后的行中的同一Day
中开始。如果当前行Journey
,则Value < InitialValue(from the first row of a journey)
将结束。一旦确定了Journey
的开始和结束,便在JourneyGroup
分组的Day
中分配了一个组号。
例如,在第一行Journey ==1
中,然后Journey
开始。在第二行中,它也是Journey==1
,但是第一行中的Journey
已经打开,因此从第二行开始,它只是从行中第一个Journey
的延续。第一排。在第4行中,分配标记Value of 2 < InitialValue of 3
和Journey
为1的结尾的JourneyGroup
。
我可以使用ngroup
或pd.categorical
来分配组并检查条件
通过执行以下操作:
df.Value<df.groupby(['Group??']).InitialValue.transform('first')
,但不确定如何在将Journey
设置为ON或OFF的同时保留内存的情况下,如何将概念进行迭代组合。
NB:-Journey
不能跨越多天,并且必须在同一天结束,就像Journey2
结束一样,即使Value
始终大于InitialValue
。 / p>
答案 0 :(得分:2)
这是一种尝试,需要更多数据进行测试:
t_num = ((df['Value'].shift() < df.groupby(['Day',df.groupby('Day')['Journey'].cummax()])['Value'].transform('first')) | df['Day'].diff().bfill().ne(0)).cumsum() + 1
m = t_num.diff().bfill().eq(1) & df.Journey.eq(0)
t_num = t_num.mask(m,0)
df['JGroup'] = t_num
df
输出:
Day Journey InitialValue Value JourneyGroup JGroup
0 12 1 3.0 4 1 1
1 12 1 4.0 5 1 1
2 12 0 NaN 7 1 1
3 12 0 NaN 2 1 1
4 12 1 5.0 8 2 2
5 12 0 NaN 9 2 2
6 13 1 3.0 4 3 3
7 13 1 4.0 5 3 3
8 13 0 NaN 7 3 3
9 13 0 NaN 6 3 3
10 13 1 1.0 2 3 3
11 13 0 NaN 9 0 0
说明:
Groupby Day并查找旅程的开始,并将当天的所有日期都设置为“旅程”,因为我们不确定旅程何时停止:
df.groupby('Day')['Journey'].cummax()
接下来,在新的groupby中使用该值,以在旅程开始时查找第一个值,并使用transform将其沿组的长度复制。
df.groupby(['Day',df.groupby('Day')['Journey'].cummax()])['Value'].transform('first')
使用,移动以与下一条记录进行比较。如果比较小于,则返回True,或者如果日期更改返回True,则表示旧旅程的结束和新旅程的开始。使用cumsum
递增计数器。
接下来使用该计数索引,需要屏蔽掉以旅途= 0开始一个新组的记录。
m = t_num.diff().bfill().eq(1) & df.Journey.eq(0)
t_num = t_num.mask(m,0)
这确实只是一个开始。我觉得这段代码不够强大,无法处理其他数据集。