Эффективное использование памяти для замены недопустимых значений в большом DataFrame? - PullRequest
0 голосов
/ 05 декабря 2018

Этот вопрос является продолжением следующего: Как заменить определенные строки значениями общего столбца в пандах DataFrame?

Допустим, у меня есть следующие панды DataFrame:

import pandas as pd

data = [['Alex',10],['Bob',12],['Clarke',13], ['Bob', '#'], ['Bob', '#'], ['Bob', '#'], ['Clarke', '#']]

df = pd.DataFrame(data,columns=['Name','Age'], dtype=float)

     Name Age
0    Alex  10
1     Bob  12
2  Clarke  13
3     Bob   #
4     Bob   #
5     Bob   #
6  Clarke   #

Строки 3-6 имеют недопустимые значения, строка #.Они должны быть заменены действительными значениями, выводя:

     Name Age
0    Alex  10
1     Bob  12
2  Clarke  13
3     Bob  12
4     Bob  12
5     Bob  12
6  Clarke  13

Обсуждаемые решения панд для замены этих значений обсуждались с использованием coerce или заменой на поднабор данных:

v = df.assign(Age=pd.to_numeric(df['Age'], errors='coerce')).dropna()
df['Age'] = df['Name'].map(v.set_index('Name').Age) 

или

d= df[df['Age']!='#'].set_index('Name')['Age']
df['Age']=df['Name'].replace(d)

Проблема заключается в DataFrame для панд с миллионами строк, эти решения на основе панд становятся очень интенсивными в памяти.

В таких ситуациях с пандами, что было бы наиболее практичным решением?

Я мог бы попытаться создать массивный словарь, используя df[df['Age']!='#'], с Name: Age в качестве пар ключ-значение.Затем перебирайте исходные панды DataFrame строка за строкой;если есть строка с возрастом == #, то замените ее на основе пары ключ-значение в словаре.Недостатком этого является то, что цикл for будет длиться вечно.

Существуют ли другие решения, которые бы имели более высокую производительность?

1 Ответ

0 голосов
/ 05 декабря 2018

Что если вы попробуете что-то более эффективное использование памяти, например, замену на основе словаря вместо последовательной?

mapping = dict(df.drop_duplicates('Name', keep='first').values)
df['Age'] = df['Name'].map(mapping)

print(df)
     Name  Age
0    Alex   10
1     Bob   12
2  Clarke   13
3     Bob   12
4     Bob   12
5     Bob   12
6  Clarke   13

Другой альтернативой будет использование понимания списка:

mapping = dict(df.drop_duplicates('Name', keep='first').values)
df['Age'] = [mapping.get(x, np.nan) for x in df['Name']]

print(df)
     Name  Age
0    Alex   10
1     Bob   12
2  Clarke   13
3     Bob   12
4     Bob   12
5     Bob   12
6  Clarke   13

Это должно работать, если в поле «Возраст» на первом месте стоят допустимые значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...