mok*_*oku 12 python dataframe pandas
我正在尝试用空列表[]替换数据中的一些NaN值.但是,列表表示为str,不允许我正确应用len()函数.无论如何用大熊猫中的实际空列表替换NaN值?
In [28]: d = pd.DataFrame({'x' : [[1,2,3], [1,2], np.NaN, np.NaN], 'y' : [1,2,3,4]})
In [29]: d
Out[29]:
x y
0 [1, 2, 3] 1
1 [1, 2] 2
2 NaN 3
3 NaN 4
In [32]: d.x.replace(np.NaN, '[]', inplace=True)
In [33]: d
Out[33]:
x y
0 [1, 2, 3] 1
1 [1, 2] 2
2 [] 3
3 [] 4
In [34]: d.x.apply(len)
Out[34]:
0 3
1 2
2 2
3 2
Name: x, dtype: int64
Run Code Online (Sandbox Code Playgroud)
EdC*_*ica 18
这可以使用isnull和loc掩盖系列:
In [90]:
d.loc[d.isnull()] = d.loc[d.isnull()].apply(lambda x: [])
d
Out[90]:
0 [1, 2, 3]
1 [1, 2]
2 []
3 []
dtype: object
In [91]:
d.apply(len)
Out[91]:
0 3
1 2
2 0
3 0
dtype: int64
Run Code Online (Sandbox Code Playgroud)
你必须这样做apply才能使列表对象不被解释为一个数组,以分配回df,它将尝试将形状与原始系列对齐
编辑
使用您更新的示例,以下工作:
In [100]:
d.loc[d['x'].isnull(),['x']] = d.loc[d['x'].isnull(),'x'].apply(lambda x: [])
d
Out[100]:
x y
0 [1, 2, 3] 1
1 [1, 2] 2
2 [] 3
3 [] 4
In [102]:
d['x'].apply(len)
Out[102]:
0 3
1 2
2 0
3 0
Name: x, dtype: int64
Run Code Online (Sandbox Code Playgroud)
您还可以为此使用列表理解:
d['x'] = [ [] if x is np.NaN else x for x in d['x'] ]
Run Code Online (Sandbox Code Playgroud)
小智 8
为了扩展公认的答案,apply 调用可能特别昂贵 - 通过从头开始构造一个 numpy 数组,可以在没有它的情况下完成相同的任务。
isna = df['x'].isna()
df.loc[isna, 'x'] = pd.Series([[]] * isna.sum()).values
Run Code Online (Sandbox Code Playgroud)
快速时序比较:
def empty_assign_1(s):
s.isna().apply(lambda x: [])
def empty_assign_2(s):
pd.Series([[]] * s.isna().sum()).values
series = pd.Series(np.random.choice([1, 2, np.nan], 1000000))
%timeit empty_assign_1(series)
>>> 172 ms ± 2.29 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%timeit empty_assign_2(series)
>>> 19.5 ms ± 116 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Run Code Online (Sandbox Code Playgroud)
快了近 10 倍!