我有一个大型的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方法执行重建索引,但我不知道替代方案是什么。似乎应该有办法我可以迭代地做一些需要更少内存的东西,但我不知道该怎么做。
答案 0 :(得分:0)
我会通过创建一个只包含所需日期的DataFrame
来解决这个问题。然后按照ID对原始DataFrame
进行分组,并使用DataFrame
加入日期outer
,以提取任何缺失的日期(因此x
和y
对于必须通过连接拉入日期的行,将为NaN
。
之后,按ID分组,按照您需要的顺序按日期排序,然后只需使用常规电话fillna
转发x
和{{中的所有NaN值1}}列。
我用y
s和>完成了这项任务之前的2亿行(在具有12 GB RAM的系统上)是的,它不是即时的,但它也不够慢。
一些伪代码:
DataFrame