如何处理修改大型pandas数据帧

时间:2015-07-22 20:30:00

标签: python pandas dask

我有一个大熊猫数据帧(磁盘上1.5gig .csv)。我可以将它加载到内存中并进行查询。我想创建一个新列,它是两个其他列的组合值,我尝试了这个:

def combined(row):
    row['combined'] = row['col1'].join(str(row['col2']))
return row

df = df.apply(combined, axis=1)

这导致我的python进程被杀死,可能是因为内存问题。

问题的一个更迭代的解决方案似乎是:

df['combined'] = ''
col_pos = list(df.columns).index('combined')
crs_pos = list(df.columns).index('col1')
sub_pos = list(df.columns).index('col2')

for row_pos in range(0, len(df) - 1):
    df.iloc[row_pos, col_pos] = df.iloc[row_pos, sub_pos].join(str(df.iloc[row_pos, crs_pos]))

这当然看起来非常不合时宜。并且非常慢。

理想情况下,我希望像apply_chunk()这样的东西与apply相同但只适用于数据帧的一部分。我认为dask可能是一个选项,但是dask数据框在我使用时似乎还有其他问题。这必须是一个常见的问题,我是否应该使用设计模式将列添加到大型pandas数据帧?

2 个答案:

答案 0 :(得分:4)

我会尝试使用列表理解+ itertools

df = pd.DataFrame({
    'a': ['ab'] * 200,
    'b': ['ffff'] * 200
})


import itertools

[a.join(b) for (a, b) in itertools.izip(df.a, df.b)]

它可能是“unpandas”,但是pandas似乎没有.str方法可以帮助你,而且它不是“unpythonic”。

要创建另一列,只需使用:

df['c'] = [a.join(b) for (a, b) in itertools.izip(df.a, df.b)]

顺便提一下,您也可以使用以下方式获取分块:

[a.join(b) for (a, b) in itertools.izip(df.a[10: 20], df.b[10: 20])]

如果你想玩并行化。我会首先尝试上面的版本,因为列表理解和itertools通常会出乎意料地快,并行化需要一个需要超过的开销。

答案 1 :(得分:1)

pandasdask.dataframe中创建新列的一种不错方法是使用.assign方法。

In [1]: import pandas as pd

In [2]: df = pd.DataFrame({'x': [1, 2, 3, 4], 'y': ['a', 'b', 'a', 'b']})

In [3]: df
Out[3]: 
   x  y
0  1  a
1  2  b
2  3  a
3  4  b

In [4]: df.assign(z=df.x * df.y)
Out[4]: 
   x  y     z
0  1  a     a
1  2  b    bb
2  3  a   aaa
3  4  b  bbbb

但是,如果你的操作是高度自定义的(如果它看起来那样)并且Python迭代器的速度足够快(就像它们看起来那样)那么你可能只想坚持下去。每当您发现自己在循环中使用applyiloc时,Pandas可能比最佳运行速度慢得多。