熊猫 - 在特定时间间隔内累积值

时间:2014-11-03 16:05:13

标签: python pandas dataframe running-total accumulator

假设我有

df

                          ts  v
0 2014-11-03 03:39:42.200914  1
1 2014-11-03 03:39:42.500914  2
2 2014-11-03 03:39:43.600914  3
3 2014-11-03 03:39:43.620914  4

我想追加一个列s,这样在每一行中,它包含1秒回顾时间间隔内v的总和,例如

desired_df
   s                         ts  v
0  1 2014-11-03 03:39:42.200914  1
1  3 2014-11-03 03:39:42.500914  2
2  3 2014-11-03 03:39:43.600914  3
3  7 2014-11-03 03:39:43.620914  4

那么,如何生成此附加列s

Noe,间隔应该重叠,但它们必须在数据帧的每一行(datapoint)都有正确的端点,即我的数据帧中的每一行(datapoint)必须是该大小的间隔的右端点。

编辑:下面的回答是不对的?完整的

编辑:我希望该解决方案适用于通用时间间隔,例如14ms,不一定只持续1秒。

怎么样

df['s'] = df.groupby(pd.TimeGrouper(freq='400mS')).transform(numpy.cumsum)

我得到了

                          ts  v  s
0 2014-11-03 03:39:42.200914  1  1
1 2014-11-03 03:39:42.500914  2  2
2 2014-11-03 03:39:43.600914  3  3
3 2014-11-03 03:39:43.620914  4  7

行索引1是不是错了?在03:39:42.500914应该是2 + 1 = 3。不是2,因为前2行都在400ms之内,所以应该将它们加在一起。为什么不这样做?

编辑:当我尝试

df['s'] = df.groupby(pd.TimeGrouper(freq='340mS')).transform(numpy.cumsum)

它实际执行该分组,即使时间间隔较小:

                            v  s
ts                              
2014-11-03 03:39:42.200914  1  1
2014-11-03 03:39:42.500914  2  3
2014-11-03 03:39:43.600914  3  3
2014-11-03 03:39:43.620914  4  7

那么,TimeGrouper所在的分隔符(分隔符)在哪里?我希望区间的正确端点与我正在查看的行(s对应的行)重合

1 个答案:

答案 0 :(得分:3)

ts设置为索引,然后设置groupby秒,然后使用cumsum()转换为新列 s ,然后应用reset_index,就像这样:

df
                          ts  v
0 2014-11-03 03:39:42.200914  1
1 2014-11-03 03:39:42.500914  2
2 2014-11-03 03:39:43.600914  3
3 2014-11-03 03:39:43.620914  4

df = df.set_index('ts')

df['s'] = df.groupby(lambda x: x.second).transform(cumsum)
df = df.reset_index()
df

                          ts  v  s
0 2014-11-03 03:39:42.200914  1  1
1 2014-11-03 03:39:42.500914  2  3
2 2014-11-03 03:39:43.600914  3  3
3 2014-11-03 03:39:43.620914  4  7

您可能需要重新排序列:

df = df[['s','ts','v']]
df
   s                         ts  v
0  1 2014-11-03 03:39:42.200914  1
1  3 2014-11-03 03:39:42.500914  2
2  3 2014-11-03 03:39:43.600914  3
3  7 2014-11-03 03:39:43.620914  4

更新

当OP更新需要通用方法时,可以使用pd.TimeGrouper

另一次更新(提供完整步骤)

df = pd.DataFrame([['2014-11-03 03:39:42.200914',1],['2014-11-03 03:39:42.500914', 2],['2014-11-03 03:39:43.600914',3],['2014-11-03 03:39:43.620914', 4]], columns=['ts','v'], dtype=object)

# you will get type error if you haven't converted your string to datetime 
df['ts'] = [pd.to_datetime(d) for d in df['ts']]

df = df.set_index('ts')

见此行

# from the doc we need to add closed='left' to include the first nbin count
df['s'] = df.groupby(pd.TimeGrouper(freq='340mS', closed='left')).transform(cumsum)

# reset the index
df = df.reset_index()

# reorder the columns
df = df[['s', 'ts', 'v']]

df
   s                         ts  v
0  1 2014-11-03 03:39:42.200914  1
1  3 2014-11-03 03:39:42.500914  2
2  3 2014-11-03 03:39:43.600914  3
3  7 2014-11-03 03:39:43.620914  4

然而,在' 400mS'我同意我们仍然没有得到愿望的结果。