我有DataFrame
,其中包含许多字符串列和日期时间列。我想使用pandas df.resample()
适当地重新采样日期时间列。例如,我的数据如下:
from pandas import *
import numpy as np
df = DataFrame({
'username' : ["bob","bob","nancy"],
'session' : ["one","two","three"],
'timestamp' : [np.datetime64("2012-12-12 17:53:36"),np.datetime64("2012-12-13 17:53:36"),np.datetime64("2012-12-14 17:53:36")] })
我添加了一个新的计数列:
df["cnt"]=1
然后,我尝试使用DataFrame
将df.resample("1D", how="sum")
重新取样为每日。这不起作用:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-44-01a264cf511c> in <module>()
----> 1 df.resample("1D", how="sum")
/usr/local/lib/python2.7/dist-packages/pandas/core/generic.pyc in resample(self, rule, how, axis, fill_method, closed, label, convention, kind, loffset, limit, base)
288 fill_method=fill_method, convention=convention,
289 limit=limit, base=base)
--> 290 return sampler.resample(self)
291
292 def first(self, offset):
/usr/local/lib/python2.7/dist-packages/pandas/tseries/resample.pyc in resample(self, obj)
98 return obj
99 else: # pragma: no cover
--> 100 raise TypeError('Only valid with DatetimeIndex or PeriodIndex')
101
102 rs_axis = rs._get_axis(self.axis)
TypeError: Only valid with DatetimeIndex or PeriodIndex
如果我将时间戳提升为索引,那似乎没有帮助,大概是因为sum()
在我的其他值上运行有麻烦。我尝试创建一个多索引然后取消堆叠几次:
df.set_index(["timestamp","username","session"], inplace=True)
df.unstack().unstack().resample("1D",how="min")
这在这里的小例子中完美无缺。在我的应用程序代码中它没有,我们得到一个内存不足的错误。下面是一个使用数据大小的示例(包括元素数量和形式,因为它们主要是md5哈希)。在具有大量内存的机器上很快就会死掉,所以也许这是一个错误?
import random
import md5
def gethash(i):
return md5.new(str(random.random())).hexdigest()
def gettimestamp(i):
return np.datetime64("2012-" + str(random.randint(10,12)) + "-" + str(random.randint(10,28)) + " 17:53:36")
df = DataFrame({
'username' : map(gethash,xrange(10000)),
'session' : map(gethash,xrange(10000)),
'timestamp' : map(gettimestamp,xrange(10000))
})
df["cnt"]=1
df.set_index(["timestamp","username","session"], inplace=True)
df.unstack().unstack().resample("1D",how="min")
我们发现的唯一工作是使用numpy数据类型截断日期。 E.g。
df['timestamp']=df.timestamp.values.astype('datetime64[D]')
这限制了astype()
演员允许的任何选项。例如,我们如何每两天重新采样一次?在熊猫中,它将是:
df.resample("2D",how="min")
(与玩具示例一起使用,但由于内存问题,不在我们的完整代码中)
是否有另一种方法可以在pandas中使用较大的数据集来获得resample()
的相同效果?
答案 0 :(得分:0)
你需要做这样的事情。这是解释。
设置时间戳索引,对时间戳索引进行排序(我在这里做的方式,你不需要排序,而重新取样 需要它排序)。并以您想要的任何频率执行重采样(本例中为1D);这相当于一个重新采样,但它只是“分组”而且还没有进行计算。
然后在申请中,进行计算,在这种情况下是另一个groupby。
In [74]: df.set_index('timestamp').sort_index().groupby(pd.TimeGrouper('1D')).apply(lambda x: x.groupby(['username','session']).sum())
Out[74]:
cnt
username session
2012-12-12 bob one 1
2012-12-13 bob two 1
2012-12-14 nancy three 1
[3 rows x 1 columns]
ATM无法一次完成所有操作(这是一个很好的请求:https://github.com/pydata/pandas/issues/3794
你的例子太简单了,无法返回任何有趣的内容(你的更大的例子太随意,没有足够的分组)。
这不应该是内存问题。你几乎从不想在一个大集合上连续两次卸载,因为它的内存是有益的。