减少复杂pandas重建索引任务的内存使用量

时间:2013-11-01 20:38:53

标签: python pandas

我有一个大型的pandas数据帧(约1300万行),其中包含各种项目的数据,每个项目都有不同月份的观察结果。项目相对于相应行的数量(即具有观察数据的月份)而变化,并且月份可能连续也可能不连续。一个高度简化的简化样本:

                          x         y
item_id date
4       2006-01-01  5.69368  0.789752
        2006-02-01  5.67199  0.786743
        2006-03-01  5.66469  0.783626
        2006-04-01  5.69427  0.782596
        2006-05-01  5.70198  0.781670
5       2006-05-01  3.16992  1.000000
        2006-07-01  3.25000  0.978347

我需要为数据完成以下操作:对于每个项目,将该项目的第一个观察行的填充观察值转发到指定的最大日期。因此,在上面的例子中,所需的输出如下:

                          x         y
item_id
4       2006-01-01  5.69368  0.789752
        2006-02-01  5.67199  0.786743
        2006-03-01  5.66469  0.783626
        2006-04-01  5.69427  0.782596
        2006-05-01  5.70198  0.781670
        2006-06-01  5.70198  0.781670
        2006-07-01  5.70198  0.781670
        2006-08-01  5.70198  0.781670
        2006-09-01  5.70198  0.781670
        2006-10-01  5.70198  0.781670
        2006-11-01  5.70198  0.781670
        2006-12-01  5.70198  0.781670
5       2006-05-01  3.16992  1.000000
        2006-06-01  3.16992  1.000000
        2006-07-01  3.25000  0.978347
        2006-08-01  3.25000  0.978347
        2006-09-01  3.25000  0.978347
        2006-10-01  3.25000  0.978347
        2006-11-01  3.25000  0.978347
        2006-12-01  3.25000  0.978347

为了便于进一步分析,我需要将日期索引转换为简单的数字索引(我们称之为“seq”),这样最终的结果是:

                  x         y
item_id seq
4       0   5.69368  0.789752
        1   5.67199  0.786743
        2   5.66469  0.783626
        3   5.69427  0.782596
        4   5.70198  0.781670
        5   5.70198  0.781670
        6   5.70198  0.781670
        7   5.70198  0.781670
        8   5.70198  0.781670
        9   5.70198  0.781670
        10  5.70198  0.781670
        11  5.70198  0.781670
5       0   3.16992  1.000000
        1   3.16992  1.000000
        2   3.25000  0.978347
        3   3.25000  0.978347
        4   3.25000  0.978347
        5   3.25000  0.978347
        6   3.25000  0.978347
        7   3.25000  0.978347

(这点是允许我对项目的第一,第二,......,第n次观察进行平均)。在任何情况下,如果我只操作数据的一个子集,我有一个解决方案可以正常工作:

df = pd.read_table(filename,sep='\s*',header=None,names=['item_id','date','x','y'],index_col=['item_id','date'],parse_dates='date')
maxDate = '2006-12-01'
def switchToSeqIndex(df):
    minDate = df.index[0][1] # get the first observed date
    return df.reset_index(level='item_id',drop=True).reset_index(). \
            set_index('date').reindex(pd.date_range(minDate,maxDate,freq='MS'), \ 
            method='ffill').reset_index('date',drop=True)
df_fixed = df.groupby(level='item_id').apply(switchToSeqIndex)
df_fixed.index.names[1]='seq'

原则上这很好,并且生成正确的输出,但是当我尝试对完整数据集执行操作(1300万行,通过重建索引扩展了大量数据)时,内存使用失控(崩溃)一台20gb ram的机器。

我的问题,那就是我如何在减少内存开销的同时实现这一目标。我认为问题是尝试使用groupby / apply方法执行重建索引,但我不知道替代方案是什么。似乎应该有办法我可以迭代地做一些需要更少内存的东西,但我不知道该怎么做。

1 个答案:

答案 0 :(得分:0)

我会通过创建一个只包含所需日期的DataFrame来解决这个问题。然后按照ID对原始DataFrame进行分组,并使用DataFrame加入日期outer,以提取任何缺失的日期(因此xy对于必须通过连接拉入日期的行,将为NaN

之后,按ID分组,按照您需要的顺序按日期排序,然后只需使用常规电话fillna转发x和{{中的所有NaN值1}}列。

我用y s和>完成了这项任务之前的2亿行(在具有12 GB RAM的系统上)是的,它不是即时的,但它也不够慢。

一些伪代码:

DataFrame