有没有办法在多个列中填充缺失值,这些列中的部分名称与另一列中的值共享?
Is there a way to fill missing values in multiple columns sharing part of their name with values from another column?
我正在尝试在多个列中填充 NaN(对于要硬编码的解决方案来说太多了),这些列的名称的一部分与同一 pandas 数据框中另一列的值共享。
我知道我可以使用常量值填充多列,也可以使用同一数据框中的另一列填充单个列。这两者的结合对我不起作用。
例如,考虑数据框:
df = pd.DataFrame({'Val': [1.2,5.4,3.1,4], 'Col - 1': [None,5,1,None], 'Col - 2': [None,None,6,None]})
print(df)
Val Col - 1 Col - 2
0 1.2 NaN NaN
1 5.4 5.0 NaN
2 3.1 1.0 6.0
3 4.0 NaN NaN
用常量值填充多个列有效:
df.loc[:,df.columns.str.contains('Col')] = df.loc[:,df.columns.str.contains('Col')].fillna(value=15)
print(df)
Val Col - 1 Col - 2
0 1.2 15.0 15.0
1 5.4 5.0 15.0
2 3.1 1.0 6.0
3 4.0 15.0 15.0
用另一列的值填充单个列也有效:
df['Col - 2'] = df['Col - 2'].fillna(value=df['Val'])
print(df)
Val Col - 1 Col - 2
0 1.2 NaN 1.2
1 5.4 5.0 5.4
2 3.1 1.0 6.0
3 4.0 NaN 4.0
两者的组合不起作用:
df.loc[:,df.columns.str.contains('Col')] = df.loc[:,df.columns.str.contains('Col')].fillna(value=df['Val'])
上面什么都不做,returns 原始数据帧。我期待的是:
Val Col - 1 Col - 2
0 1.2 1.2 1.2
1 5.4 5.0 5.4
2 3.1 1.0 6.0
3 4.0 4.0 4.0
这是解决 np.where
问题的方法:
cols = [col for col in df.columns if 'Col' in col]
df[cols] = np.where(df[cols].isna(), df.Val.values[:,None], df[cols])
输出:
Val Col - 1 Col - 2
-- ----- --------- ---------
0 1.2 1.2 1.2
1 5.4 5 5.4
2 3.1 1 6
3 4 4 4
你应该添加 apply
lambda
,因为数据帧 fillna
也会检查 columns
name ,你用 pd.Series
填充它不匹配 columns
,所以会使 fillna 失败
df.loc[:,df.columns.str.contains('Col')].apply(lambda x : x.fillna(value=df['Val']))
您可以在此处使用 df.filter()
:
m=df.filter(like='Col')
df[m.columns]=m.apply(lambda x: x.fillna(df.Val))
print(df)
Val Col - 1 Col - 2
0 1.2 1.2 1.2
1 5.4 5.0 5.4
2 3.1 1.0 6.0
3 4.0 4.0 4.0
我正在尝试在多个列中填充 NaN(对于要硬编码的解决方案来说太多了),这些列的名称的一部分与同一 pandas 数据框中另一列的值共享。
我知道我可以使用常量值填充多列,也可以使用同一数据框中的另一列填充单个列。这两者的结合对我不起作用。
例如,考虑数据框:
df = pd.DataFrame({'Val': [1.2,5.4,3.1,4], 'Col - 1': [None,5,1,None], 'Col - 2': [None,None,6,None]})
print(df)
Val Col - 1 Col - 2
0 1.2 NaN NaN
1 5.4 5.0 NaN
2 3.1 1.0 6.0
3 4.0 NaN NaN
用常量值填充多个列有效:
df.loc[:,df.columns.str.contains('Col')] = df.loc[:,df.columns.str.contains('Col')].fillna(value=15)
print(df)
Val Col - 1 Col - 2
0 1.2 15.0 15.0
1 5.4 5.0 15.0
2 3.1 1.0 6.0
3 4.0 15.0 15.0
用另一列的值填充单个列也有效:
df['Col - 2'] = df['Col - 2'].fillna(value=df['Val'])
print(df)
Val Col - 1 Col - 2
0 1.2 NaN 1.2
1 5.4 5.0 5.4
2 3.1 1.0 6.0
3 4.0 NaN 4.0
两者的组合不起作用:
df.loc[:,df.columns.str.contains('Col')] = df.loc[:,df.columns.str.contains('Col')].fillna(value=df['Val'])
上面什么都不做,returns 原始数据帧。我期待的是:
Val Col - 1 Col - 2
0 1.2 1.2 1.2
1 5.4 5.0 5.4
2 3.1 1.0 6.0
3 4.0 4.0 4.0
这是解决 np.where
问题的方法:
cols = [col for col in df.columns if 'Col' in col]
df[cols] = np.where(df[cols].isna(), df.Val.values[:,None], df[cols])
输出:
Val Col - 1 Col - 2
-- ----- --------- ---------
0 1.2 1.2 1.2
1 5.4 5 5.4
2 3.1 1 6
3 4 4 4
你应该添加 apply
lambda
,因为数据帧 fillna
也会检查 columns
name ,你用 pd.Series
填充它不匹配 columns
,所以会使 fillna 失败
df.loc[:,df.columns.str.contains('Col')].apply(lambda x : x.fillna(value=df['Val']))
您可以在此处使用 df.filter()
:
m=df.filter(like='Col')
df[m.columns]=m.apply(lambda x: x.fillna(df.Val))
print(df)
Val Col - 1 Col - 2
0 1.2 1.2 1.2
1 5.4 5.0 5.4
2 3.1 1.0 6.0
3 4.0 4.0 4.0