内存有效的解决方案来替换大型DataFrame中的无效值?

时间:2018-12-05 13:06:15

标签: python pandas performance dataframe

此问题是以下内容的继续: How to replace certain rows by shared column values in 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

为替换这些讨论的值而讨论的熊猫解决方案是使用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,这些基于pandas的解决方案非常占用内存。

在像这样的大熊猫情况下,最实用的解决方案是什么?

我可以尝试使用df[df['Age']!='#']作为键值对使用Name: Age创建大型词典。然后,逐行遍历原始的熊猫DataFrame;如果存在年龄== {#的行,则根据字典中的键值对替换它。不利的一面是,for循环将永远存在。

是否还有其他具有更好性能的解决方案?

1 个答案:

答案 0 :(得分:1)

如果您尝试使用内存效率更高的东西(例如基于字典的替换而不是基于序列的替换)怎么办?

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

假定“年龄”中的有效值排在首位,这应该可以工作。