使用Pandas DataFrame计算状态的持续时间

5

我试图计算一个状态被进入的频率和持续时间。例如,我有三种可能的状态1、2和3,哪个状态是活动的在pandas数据框中被记录:

test = pd.DataFrame([2,2,2,1,1,1,2,2,2,3,2,2,1,1], index=pd.date_range('00:00', freq='1h', periods=14))

例如,状态1被输入两次(在索引3和12处),第一次持续三个小时,第二次持续两个小时(因此平均为2.5小时)。状态2被输入3次,平均为2.66小时。
我知道我可以屏蔽我不感兴趣的数据,例如分析状态1:
state1 = test.mask(test!=1)

但是从那里开始,我找不到继续前进的方法。
1个回答

7
我希望评论中已经足够解释了 - 关键点是你可以使用自定义的滚动窗口函数,然后对其进行累加以将行分组为相同状态的“簇”。
# set things up
freq = "1h"
df = pd.DataFrame(
    [2,2,2,1,1,1,2,2,2,3,2,2,1,1],
    index=pd.date_range('00:00', freq=freq, periods=14)
)

# add a column saying if a row belongs to the same state as the one before it
df["is_first"] = pd.rolling_apply(df, 2, lambda x: x[0] != x[1]).fillna(1)

# the cumulative sum - each "clump" gets its own integer id
df["value_group"] = df["is_first"].cumsum()

# get the rows corresponding to states beginning
start = df.groupby("value_group", as_index=False).nth(0)
# get the rows corresponding to states ending
end = df.groupby("value_group", as_index=False).nth(-1)

# put the timestamp indexes of the "first" and "last" state measurements into
# their own data frame
start_end = pd.DataFrame(
    {
        "start": start.index,
        # add freq to get when the state ended
        "end": end.index + pd.Timedelta(freq),
        "value": start[0]
    }
)
# convert timedeltas to seconds (float)
start_end["duration"] = (
    (start_end["end"] - start_end["start"]).apply(float) / 1e9
)
# get average state length and counts
agg = start_end.groupby("value").agg(["mean", "count"])["duration"]
agg["mean"] = agg["mean"] / (60 * 60)

并且输出:

           mean  count
value                 
1      2.500000      2
2      2.666667      3
3      1.000000      1

我理解你解决问题的基本思路,但我对groupby方法不熟悉,而且正是这些方法导致了TypeError错误:只能将列表(而不是“int”)连接到列表中(包括start =end =两行)。 - MichaelA
1
我正在使用 Pandas 0.16.0。我认为在旧版本中,groupby().nth 的行为是不同的。尝试使用 .nth(0) 而不是 .nth([0])。(将更新答案以反映这一点) - nrg
好的,这就是原因,如果我使用nth(0),你的代码对我有效,我仍然在使用Pandas 0.13.1...接下来的问题是pd.Timedelta,在我的版本中不存在。但没关系,我会从这个点开始解决,剩下的部分我自己想办法解决。非常感谢。 - MichaelA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接