Как справиться с модификацией больших pandas данных

91
10

У меня довольно большой pandas dataframe (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(), которое будет таким же, как и применимо, но работает только над частью фрейма данных. Я думал, что dask может быть вариантом для этого, но dask у dataframes, похоже, были другие проблемы, когда я их использовал. Это должно быть общей проблемой, хотя, есть ли шаблон проектирования, который я должен использовать для добавления столбцов в большие pandas данные?

спросил(а) 2015-07-22T23:30:00+03:00 5 лет, 3 месяца назад
1
Решение
90

Я бы попытался использовать понимание списка + 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, который поможет вам здесь, и он не "неспокойный".


Чтобы создать другой столбец, просто используйте:

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 часто бывают неожиданно быстрыми, и для распараллеливания потребуются накладные расходы, которые необходимо перевесить.

ответил(а) 2015-07-22T23:44:00+03:00 5 лет, 3 месяца назад
58

Один хороший способ создать новый столбец в pandas или dask.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 достаточно быстры (как они кажутся), вы можете просто захотеть придерживаться этого. В любое время, когда вы используете apply или iloc в цикле, вероятно, что Pandas работает намного медленнее, чем оптимально.

ответил(а) 2015-07-23T01:25:00+03:00 5 лет, 3 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема