pandas时间序列diff()恢复为Series
我正在处理一些时间序列数据,格式如下:
1984-12-12 14:08:00
1984-12-12 14:25:00
1984-12-12 14:47:00
1984-12-12 16:37:00
1984-12-12 16:37:00
1984-12-12 16:37:00
1984-12-12 17:52:00
1984-12-12 17:52:00
1984-12-12 19:29:00
在过去的几天里,本来看起来很简单的操作(一个愉快的下午),却变得复杂而令人沮丧。
顺便说一下,这里是我的需求:
- 计算时间序列中某些行之间的差值
- 生成这些差值的累积和
首先,当我接触到pandas和整个 group-apply-combine
的方法时,我通常会:
- 在数据框中创建一些分组
- 编写一个函数,接受一个分组对象并返回一个分组对象
- 使用lambda函数将分组传递给这个函数
我认为这是标准做法,我喜欢这样做的原因是可以隐式地连接分组、处理多个列和插入新列。(这也避免了对分组的循环,使向量化更简单)……但我觉得它在处理空分组时有些麻烦……
无论如何,为了获取时间序列的差值,我发现使用 shift()
来获取时间差时会抛出 StopIteration
错误,而使用 diff(1)
则没有错误。
不过,新的差值列(事件行之间的时间差)变成了一个序列。
time ev delta
1984-12-12 14:08:00 1 NaT
1984-12-12 14:25:00 1 00:17:00
1984-12-12 14:47:00 1 00:22:00
1984-12-12 16:37:00 0 01:50:00
1984-12-12 16:37:00 1 01:50:00
1984-12-12 16:37:00 0 01:50:00
1984-12-12 17:52:00 0 01:15:00
1984-12-12 17:52:00 1 01:15:00
1984-12-12 19:29:00 1 01:37:00
尝试将序列转换为时间序列并没有成功。由于格式问题(发现了一个很长的数字+L,不符合小时、分钟、秒的格式),这显然中止了整个尝试,而尝试捕获错误也无法解决这个问题。
try:
pd.to_datetime(d['delta'], format='%H:%M:%S')
except:
pass
另一个不断出现的错误是从时间中获取总和时的 StopIteration
错误。
gg['cumt'] = pd.rolling_apply( gg['time'], 2, np.sum )
gg['cumt'] = pd.rolling_sum(gg['time'],2).shift(1)
gg['cumt'] = gg.apply(lambda x: pd.expanding_sum(x['time'], min_periods=2) )
我相信一个简单的 cumsum
没有抛出错误,gg['cumt'] = gg['tavg'].cumsum()
,但时间格式问题导致字符串转换为某个整数,然后它们被当作小数字相加。
任何帮助,无论是一般性的还是具体的,都非常感谢:
我喜欢编写一个函数并返回一个分组的简单想法。还没有深入探索 transform
函数(我觉得我无法让它工作);在函数中返回修改后的分组是否可以消除对变换/广播的需求?这是否是导致我出现 StopIteration
错误的原因?我感觉它无法处理某些分组为空的情况?
1 个回答
这是关于使用Pandas和Numpy这两个库的内容。Pandas是一个用来处理数据的工具,而Numpy则是用来进行数学计算的。这里提到的版本号,比如Pandas 0.12.0和Numpy 1.7.1,表示这些工具的具体版本。Python 2.7.5是使用的编程语言的版本,而Linux Mint是操作系统的名称。
import pandas as pd
import StringIO
data = '''time
1984-12-12 14:08:00
1984-12-12 14:25:00
1984-12-12 14:47:00
1984-12-12 16:37:00
1984-12-12 16:37:00
1984-12-12 16:37:00
1984-12-12 17:52:00
1984-12-12 17:52:00
1984-12-12 19:29:00'''
df = pd.read_csv(StringIO.StringIO(data))
df['time'] = pd.DatetimeIndex(df['time'])
df['delta'] = df['time'].diff()
#df['delta'] = pd.TimeSeries(df['delta']) # sorry, not needed
#df['delta'][0] = 0 # to remove NaT
# better method to remove NaT - thanks to Jeff
df['delta'] = df['delta'].fillna(0)
df['cumsum'] = df['delta'].cumsum()
print df
结果
time delta cumsum
0 1984-12-12 14:08:00 00:00:00 00:00:00
1 1984-12-12 14:25:00 00:17:00 00:17:00
2 1984-12-12 14:47:00 00:22:00 00:39:00
3 1984-12-12 16:37:00 01:50:00 02:29:00
4 1984-12-12 16:37:00 00:00:00 02:29:00
5 1984-12-12 16:37:00 00:00:00 02:29:00
6 1984-12-12 17:52:00 01:15:00 03:44:00
7 1984-12-12 17:52:00 00:00:00 03:44:00
8 1984-12-12 19:29:00 01:37:00 05:21:00