用一列的值替换DataFrame中的空值

5
假设我有以下pandas数据框:
df = pd.DataFrame([[3, 2, np.nan, 0],
                    [5, 4, 2, np.nan],
                    [7, np.nan, np.nan, 5],
                    [9, 3, np.nan, 4]],
                    columns=list('ABCD'))

它返回这个:

   A    B    C    D
0  3  2.0  NaN  0.0
1  5  4.0  2.0  NaN
2  7  NaN  NaN  5.0
3  9  3.0  NaN  4.0

我希望如果发现np.nan,将其替换为A列中的值。这意味着结果应该是这样的:
   A    B    C    D
0  3  2.0  3.0  0.0
1  5  4.0  2.0  5.0
2  7  7.0  7.0  5.0
3  9  3.0  9.0  4.0

我尝试了多种方法,但都没有成功。有人可以帮忙吗?

4个回答

6

这里需要进行双重转置:

cols = ['B','C', 'D']
df[cols] = df[cols].T.fillna(df['A']).T
print(df)
   A    B    C    D
0  3  2.0  3.0  0.0
1  5  4.0  2.0  5.0
2  7  7.0  7.0  5.0
3  9  3.0  9.0  4.0

因为:

df[cols] = df[cols].fillna(df['A'], axis=1)
print(df)

NotImplementedError: 目前只能按列用字典/系列填充

使用 numpy.where 和列广播 A 的另一种解决方案:

df = pd.DataFrame(np.where(df.isnull(), df['A'].values[:, None], df), 
                  index=df.index, 
                  columns=df.columns)
print (df)
     A    B    C    D
0  3.0  2.0  3.0  0.0
1  5.0  4.0  2.0  5.0
2  7.0  7.0  7.0  5.0
3  9.0  3.0  9.0  4.0

感谢 @pir 提供的另一种解决方案:
df = pd.DataFrame(np.where(df.isnull(), df[['A']], df), 
                  index=df.index, 
                  columns=df.columns)

1
真是令人惊讶,一个看似简单的任务竟需要如此灵活的技巧。+1 - ALollz
1
对于 np.wherenp.where(df.isna(), df[['A']], df) - piRSquared
1
感谢您的回答,@jezrael。您提供的两个解决方案都可以工作,但第一个解决方案仍在运行中,我正在输入此内容时,它正在尝试在我的完整数据集上完成。然而,第二个解决方案非常快速。 - user498537
@user498537 - 是的,在大型数据框中第二种方法更快。 - jezrael

5

目前,fillna不允许在对齐索引的同时跨列广播系列。

pandas.DataFrame.mask

这个函数的功能与我们想让fillna执行的相同。找到空值,在axis=0上沿着df.A填充它。

df.mask(df.isna(), df.A, axis=0)

   A    B    C    D
0  3  2.0  3.0  0.0
1  5  4.0  2.0  5.0
2  7  7.0  7.0  5.0
3  9  3.0  9.0  4.0

pandas.DataFrame.fillna使用字典

但是,您可以将一个字典传递给 fillna,告诉它对每一列要做什么。

df.fillna({k: df.A for k in df})

   A    B    C    D
0  3  2.0  3.0  0.0
1  5  4.0  2.0  5.0
2  7  7.0  7.0  5.0
3  9  3.0  9.0  4.0

3

使用 reindexfillna 填充数据

df.fillna(df[['A']].reindex(columns=df.columns).ffill(1))
Out[20]: 
   A    B    C    D
0  3  2.0  3.0  0.0
1  5  4.0  2.0  5.0
2  7  7.0  7.0  5.0
3  9  3.0  9.0  4.0

或者combine_first
df.combine_first(df.fillna(0).add(df.A,0))
Out[35]: 
   A    B    C    D
0  3  2.0  3.0  0.0
1  5  4.0  2.0  5.0
2  7  7.0  7.0  5.0
3  9  3.0  9.0  4.0

0
# for each column...
for col in df.columns:
    # I select the np.nan and I replace then with the value of A
    df.loc[df[col].isnull(), col] = df["A"]

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