在Pandas中使用最后计算值进行顺序计算
有没有人能建议一种方法,让我可以按顺序应用一个函数,这样不仅能使用正在计算的列的最后计算值,还能使用其他列当前和过去的值,来处理一个pandas数据框。
为了说明我的使用场景,假设我有一个数据框,其中有“开始”和“结束”标记,用于表示一个事件的发生,我需要在一个叫“事件”的新列中标记事件的发生,用“1”表示。以下是各列的描述:
- 开始:当条件满足时,这列标记为1,表示事件开始。如果这一列有1,说明要么是事件开始,要么是已经存在的事件在继续,即使“结束”列标记为2。
- 结束:当条件满足时,这列标记为2,表示事件结束,前提是“开始”列为0。如果“开始”列为1,那么这些值对正在进行的事件没有影响。
- 事件:这一列需要计算,标记为1的行表示事件正在进行。
这个例子的逻辑是,我用1开始事件,并在1和2重叠时或在接下来的两个值结束时结束事件。
Start End Event 1 0 0 0 2 1 2 1 3 1 2 1 4 0 0 0 5 0 0 0 6 0 0 0 7 1 0 1 8 0 2 1 9 0 2 0 10 0 0 0
我明白,如果我能找到一种方法,按顺序使用其他列的当前行值来实现一个函数,我就可以轻松地使用这些列的过去值,方法是用.shift(...)。到目前为止,我找到了一种在同一列上进行顺序计算的python实现:https://groups.google.com/forum/#!topic/pydata/0MCWhwurOWs,还有这段python代码:https://github.com/pydata/pandas/issues/4567
我从来没有使用过cython,想知道是否可以用上述方法来实现。
总的来说,我觉得pandas缺少一种简单的计算方式,让我不仅能参考其他列的值,还能参考同一列的计算值,以便对当前行进行计算。这很困难,因为pandas是基于列的,并且应用的是基于列的数组函数。
我非常希望能得到帮助。
1 个回答
0
好的,即使在澄清之后,你的问题还是不太清楚。你给的例子实际上违反了你自己的定义,因为第二行开始的事件从来没有结束,因为第三行和第四行都没有满足你目前所说的结束条件:(“如果开始为1,结束为2的值对正在进行的事件没有任何影响?!)”
不过,这里有一个大致的解决思路,你可以在这个基础上进行调整,剩下的部分你可以自己搞定:
- 你需要用到的工具是
diff
和cumsum
。你还需要做一些布尔计算。 diff()
会给你正的和负的变化;因为你只关心最早的正变化,所以可以比较diff(...) == +1
的输出。- 在这里,我们计算两个中间向量 event_started 和 event_ended,然后将它们转换成整数,这样我们就可以进行累加和
cumsum(as.integer(event_started) - as.integer(event_ended))
,这似乎正是你想要的:
.
df <- data.frame(Start=c(0,1,1,0,0,0,1,0,0,0), End=c(0,2,2,0,0,0,0,2,2,0))
event_started <- c(F, diff(df$Start)) == +1
FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
event_ended <- c(F, diff(df$End==2) == +1) & !event_started
FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
cumsum(as.integer(event_started) - as.integer(event_ended))
0 1 1 1 1 1 2 1 1 1
df$Event <- cumsum(as.integer(event_started) - as.integer(event_ended))