Этот вопрос является продолжением следующего: как заменить определенные строки на общие значения столбцов в pandas 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
Решения pandas, обсуждавшиеся для замены этих значений, обсуждались с использованием 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)
Проблема в том, что для pandas DataFrame с миллионами строк эти решения на основе панд становятся очень интенсивными в памяти.
В ситуациях, подобных этим с пандами, какое было бы наиболее практичное решение?
Я мог бы попытаться создать массивный словарь, используя df[df['Age']!='#']
, С Name: Age
в качестве пар ключ-значение. Затем, итерации через оригинальные панды DataFrame подряд за строкой; если есть строка с Age == #
, то замените ее на основе пары ключ-значение в словаре. Недостатком этого является то, что for-loop будет навсегда.
Существуют ли другие решения, которые будут иметь лучшую производительность?
Что делать, если вы попробуете что-то более эффективную с точки зрения памяти, например, вместо замены на основе словаря?
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
Это должно работать, если вначале должны быть действительные значения в "Возраст".
memory_usage
?
d= df[df['Age']!='#'].set_index('Name')['Age']
сколько памяти потребляетd
по сравнению сdf
?