我有一个 pandas 数据框,其中的值有时会变为 NA。我想用与另一列长度相同的字符串列表填充此列:
import pandas as pd
import numpy as np
df = pd.DataFrame({"a": ["one", "two"],
"b": ["three", "four"],
"c": [[1, 2], [3, 4]],
"d": [[5, 6], np.nan]})
a | b | c | d |
---|---|---|---|
一个 | 三 | [1, 2] | [5, 6] |
两个 | 福 | [3, 4] | NaN |
我希望这成为
a | b | c | d |
---|---|---|---|
一个 | 三 | [1, 2] | [5, 6] |
两个 | 福 | [3, 4] | [无值,无值] |
df["d"] = np.where(df.d.isna(),
[np.nan for element in df.c],
df.d) # this doesn't work
我试过了
df["d"] = np.where(df.d.isna(),
['no_value' for element in df.c],
df.d)
和
df["d"] = np.where(df.d.isna(),
['no_value'] * len(df.c),
df.d)
但是两者都不起作用。有人有想法吗?
np.where
。
df.assign(d = np.where(
df['d'].isna(),
pd.Series([['no_value'] * len(lst) for lst in df['c']]),
df['d']))
另一种可能的解决方案,它使用:
apply
在 df
上,使用 lambda 函数迭代每一行,检查列 d
中的值是否为 NaN
。
如果满足条件,该函数会生成一个新列表,其中填充字符串
'no_value'
,并重复以匹配列c
中列表的长度。
如果
x['d']
不满足这些条件,则保留x['d']
中的原始值。
df['d'] = df.apply(
lambda x: ['no_value'] * len(x['c'])
if (x['d'] is np.nan) else x['d'], axis=1)
输出:
a b c d
0 one three [1, 2] [5, 6]
1 two four [3, 4] [no_value, no_value]
要使用
where
,我们必须构造一个正确的 nan
包含数组,类似于 df.d
,具有对象数据类型列表。
In [317]: df1=df.copy();df1
Out[317]:
a b c d
0 one three [1, 2] [5, 6]
1 two four [3, 4] NaN
要完全控制,请从
empty
对象数据类型数组开始,然后填充它。
In [318]: x=np.empty(len(df.c), object)
In [319]: x[:] = [[np.nan]*len(element) for element in df.c]; x
Out[319]: array([list([nan, nan]), list([nan, nan])], dtype=object)
如果
df.c
列表的长度不同,则不需要这两个步骤。 现在 where
可以使用 [False, True]
条件在 2 个对象数据类型数组的元素之间进行选择。
In [320]: df1.d = np.where(df.d.isna(), x, df.d)
In [321]: df1
Out[321]:
a b c d
0 one three [1, 2] [5, 6]
1 two four [3, 4] [nan, nan]
In [326]: x = [[np.nan]*len(element) for element in df.c]; x
Out[326]: [[nan, nan], [nan, nan]]
不行,因为它是 (2,2) 形状,并且
where
在使用其他项((2,) 系列)“广播”该形状时会遇到问题。
或者你可以将
x
初始化为
x = df.c.copy()