当pandas中出现小数据时,DataFrame.resample()被调用时,内存不足

2024-07-03 02:16:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个DataFrame,它有许多字符串列和一个datetime列。我想使用pandasdf.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")] })

我添加了一个新的列进行计数:

^{pr2}$

然后我尝试用df.resample("1D", how="sum")DataFrame重新采样到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

如果我将时间戳提升为索引,这似乎没有帮助,大概是因为sum()在我的其他值上运行有问题。我尝试创建一个多重索引,然后拆了几次:

df.set_index(["timestamp","username","session"], inplace=True)
df.unstack().unstack().resample("1D",how="min")

这在这里的小例子中非常有效。在我的应用程序代码中没有,我们得到一个内存不足的错误。下面是一个使用数据大小的示例(包括元素数量和形式,因为它们大多是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数据类型截断日期。E、 g

df['timestamp']=df.timestamp.values.astype('datetime64[D]')

这将我们限制在astype()转换允许的任何选项。例如,我们如何每两天进行一次重新采样?在熊猫身上,它将是:

df.resample("2D",how="min")

(它适用于玩具示例,但由于内存问题而不能在完整代码中使用)

在大熊猫身上使用更大的数据集,有没有其他方法可以得到相同的效果?在


Tags: importselfdataframedfreturnsessionnpusername
1条回答
网友
1楼 · 发布于 2024-07-03 02:16:30

你需要做这样的事。解释如下。在

设置时间戳索引,对时间戳索引进行排序(就像我在这里所做的那样,您不需要排序,而重采样需要排序)。然后以任何你想要的频率(在本例中是1D)执行重采样;这相当于一次重采样,但它只是“分组”,不进行计算(还没有)。在

然后在apply中进行计算,在本例中是另一个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

您的示例太简单,无法返回任何有趣的内容(而且您的大型示例太随机,没有足够的分组)。在

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

相关问题 更多 >