Python 在小数据集上调用DataFrame.resample()时内存不足

Python 在小数据集上调用DataFrame.resample()时内存不足,python,datetime,numpy,pandas,Python,Datetime,Numpy,Pandas,我有一个DataFrame,它有许多字符串列和一个datetime列。我想使用pandas df.resample对datetime列进行适当的重采样。例如,我的数据如下所示: from pandas import * import numpy as np df = DataFrame({ 'username' : ["bob","bob","nancy"], 'session' : ["one","two","three"], 'timestamp' : [np.datetime64("20

我有一个DataFrame,它有许多字符串列和一个datetime列。我想使用pandas df.resample对datetime列进行适当的重采样。例如,我的数据如下所示:

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
然后我尝试使用df.resample1D,how=sum将数据帧重新采样为daily。这不起作用:

---------------------------------------------------------------------------
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
在这里的小示例中,这非常有效。在我的应用程序代码中没有,我们得到了一个内存不足错误。下面是一个示例,它在元素数量和形式上都使用数据大小,因为它们大多是md5哈希。这在一台有大量内存的机器上很快就会消失,所以这可能是一个bug

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数据类型截断日期。例如

df['timestamp']=df.timestamp.values.astype('datetime64[D]')
这将限制我们使用astype cast允许的任何选项。例如,我们怎样才能每两天重新采样一次?在熊猫中,它将是:

df.resample("2D",how="min")
这适用于玩具示例,但不适用于我们的完整代码,因为内存问题


有没有其他方法可以在大熊猫中使用更大的数据集获得同样的重采样效果?

您需要这样做。这是解释

设置一个时间戳索引,按照我在这里的方式对时间戳索引进行排序,你不需要排序,而重采样需要排序。并在本例中以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]
这是不可能一次完成的,这是一个未决的请求:

您的示例太简单,无法返回任何有趣的内容,而您更大的示例太随机,分组不够


这不应该是内存问题。你几乎不想在一个大集合上连续两次取消堆叠,因为它有助于记忆。

你使用的是哪个版本的熊猫?你能清楚地解释一下你想要获得的确切“效果”吗?因为在您的示例中,所有用户名和会话值都是唯一的?在用户名和会话上执行groupby并在这些组上重新采样是一个可能的方向吗?@joris我使用的是0.12版。0@joris我想要的效果是将时间戳舍入/截断为任意分组。因此,由于能够将它们截断为一天、两天等等,我更愿意使用pandas格式,而不是前面提到的numpy数据类型。我的例子很不幸,但我无法共享我的数据集-在我的原始数据集中,会话和用户有许多重复的web日志,一次使用多个会话,会话中有许多时间戳。这似乎可以做到,谢谢!我不能说我理解为什么另一种方法不起作用,概念上有什么问题吗?我应该提交一个bug吗?数据透视表也会抛出一个内存错误。为了澄清这一点,首先要按时间对所有内容进行分组,然后再根据散列的用户名进行分组。所以,如果我有更多的字符串列,我需要继续嵌套groupby函数,直到只剩下数值为止?不,你不需要再嵌套了;这是一个错误,现在你不能按时间和一个或多个字符串字段分组。方法u建议多个unstacking工作,但会破坏内存,因为它不打算这样使用
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]