Pandas使用查找表进行fillna

6

我在填充NaN时遇到了一些问题。我想要将一个包含几个NaN的数据框列,用从“查找表”中派生的值来填充它们,该值基于另一列的值。(您可能会从泰坦尼克号数据集中认出我的数据)...

    Pclass   Age
0   1        33
1   3        24
2   1        23
3   2        NaN
4   1        Nan

我希望用'series' pclass_lookup的值来填充NaN值:
pclass_lookup
1        38.1
2        29.4
3        25.2

我尝试使用索引来执行fillna操作,例如:

df.Age.fillna(pclass_lookup[df.Pclass]), but it gives me an error of 
    ValueError: cannot reindex from a duplicate axis

lambda表达式也是一种尝试:

df.Age.map(lambda x: x if x else pclass_lookup[df.Pclass]

但是,这似乎也不完全正确。我是不是完全误解了这里的意思?'

3个回答

8

首先,您在第4行有一个错误的值,实际上您有一个字符串“Nan”,它与“NaN”不同,因此即使您的代码有效,此值也永远不会被替换。

因此,您需要替换该错误的值,然后可以调用map来执行对NaN值的查找:

In [317]:

df.Age.replace('Nan', np.NaN, inplace=True)
df.loc[df['Age'].isnull(),'Age'] = df['Pclass'].map(df1.pclass_lookup)
df
Out[317]:
   Pclass   Age
0       1    33
1       3    24
2       1    23
3       2  29.4
4       1  38.1

时间

对于一个包含5000行的数据框:

In [26]:

%timeit df.loc[df['Age'].isnull(),'Age'] = df['Pclass'].map(df1.pclass_lookup)
100 loops, best of 3: 2.41 ms per loop
In [27]:

%%timeit
def remove_na(x):
    if pd.isnull(x['Age']):
        return df1[x['Pclass']]
    else:
        return x['Age']
df['Age'] =df.apply(remove_na, axis=1)
1 loops, best of 3: 278 ms per loop
In [28]:

%%timeit
nulls = df.loc[df.Age.isnull(), 'Pclass']
df.loc[df.Age.isnull(), 'Age'] = df1.loc[nulls].values
100 loops, best of 3: 3.37 ms per loop

所以,您可以看到,在逐行迭代的情况下应用比其他两种向量化方法的性能差,但是map仍然是最快的。


所有三个答案都完美地运行了。vrajs5的函数非常简单明了。这个答案虽然看起来很密集,但正是我想要做的。附:抱歉打错了“Nan”。 - zampy
你可能会发现像这样调用 map 会是最快的方法。 - EdChum

1

在 @vrajs5 的回答基础上构建:

# Create dummy data
df = pd.DataFrame()
df['Pclass'] = [1,3,1,2,1]
df['Age'] = [33,24,23,None, None]
pclass_lookup = pd.Series([38.1,29.4,25.2], index = range(1,4))

# Solution:
nulls = df.loc[df.Age.isnull(), 'Pclass']
df.loc[df.Age.isnull(), 'Age'] = pclass_lookup.loc[nulls].values

>>> df
   Pclass   Age
0       1  33.0
1       3  24.0
2       1  23.0
3       2  29.4
4       1  38.1

0

以下应该适合您:

df = pd.DataFrame()
df['Pclass'] = [1,3,1,2,1]
df['Age'] = [33,24,23,None, None]
df
   Pclass  Age
0       1   33
1       3   24
2       1   23
3       2  NaN
4       1  NaN

pclass_lookup = pd.Series([38.1,29.4,25.2], index = range(1,4))
pclass_lookup
1    38.1
2    29.4
3    25.2
dtype: float64

def remove_na(x):
    if pd.isnull(x['Age']):
        return pclass_lookup[x['Pclass']]
    else:
        return x['Age']
df['Age'] =df.apply(remove_na, axis=1)

   Pclass   Age
0       1  33.0
1       3  24.0
2       1  23.0
3       2  29.4
4       1  38.1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接