在 Pandas 数据框中水平填充单元格值

Filling cell values horizontally in Pandas dataframe

我知道 bfill 和 ffill 可以在同一列的行中填充值。但是,当您需要在数据框中的某些多列中填充值时,您该怎么做呢?

示例如下:

初始 df:

import pandas as pd
inidf = [('Prod', ['P1', 'P2']),
 ('A', ['1', '1']),
 ('1', ['', '40']),
 ('2', ['10', '60']),
 ('3', ['30', '']),
 ('B', ['1', '2']),             
 ]
df = pd.DataFrame.from_items(inidf)
df

  Prod  A   1   2   3  B
0   P1  1      10  30  1
1   P2  1  40  60      2

目标 df:

tgtdf = [('Prod', ['P1', 'P2']),
 ('A', ['1', '1']),
 ('1', ['10', '40']),
 ('2', ['10', '60']),
 ('3', ['30', '60']),
 ('B', ['1', '2']),             
 ]
df2 = pd.DataFrame.from_items(tgtdf)
df2

  Prod  A   1   2   3  B
0   P1  1  10  10  30  1
1   P2  1  40  60  60  2

在我上面的示例中,要定位的列是名为 1、2 和 3 的列。在第一行中,第一个目标列(名为 1)有一个缺失值,并且是从下一个填充的列中复制的这种情况(命名为 2)。在第二行中,最后一个目标列(名为 3)有一个缺失值,在本例中是从先前填充的列(名为 2)中复制的。

首先,用 NaN 值替换空引号。然后根据需要进行 ffill 或 bfill,指定 axis=0。当 select 给定行时,轴是 0,因为这样的 selection 的结果是一个系列。如果你要 select 多行(例如整个数据框),那么轴将是 1

df = df.replace('', np.nan)
df.iloc[0, :].bfill(axis=0, inplace=True)  # Backfill first row.
df.iloc[1, :].ffill(axis=0, inplace=True)  # Forwardfill second row.

>>> df
  Prod  A   1   2   3  B
0   P1  1  10  10  30  1
1   P2  1  40  60  60  2

您可以先使用 replace 将空格转换为 NaNs。

然后 select 行 bfillffill 替换为 axis=1 替换行:

df = df.replace('', np.nan)
bfill_rows = [0] #if necessary specify more values of index
ffill_rows = [1] #if necessary specify more values of index

df.loc[bfill_rows] = df.loc[bfill_rows].bfill(axis=1)
df.loc[ffill_rows] = df.loc[ffill_rows].ffill(axis=1)
print (df)
  Prod  A   1   2   3  B
0   P1  1  10  10  30  1
1   P2  1  40  60  60  2

如有必要,还可以指定列:

df = df.replace('', np.nan)
cols = ['1','2','3']
bfill_rows = [0]
ffill_rows = [1]

df.loc[bfill_rows, cols] = df.loc[bfill_rows, cols].bfill(axis=1)
df.loc[ffill_rows, cols] = df.loc[ffill_rows, cols].ffill(axis=1)
print (df)

  Prod  A   1   2   3  B
0   P1  1  10  10  30  1
1   P2  1  40  60  60  2

将所有空格替换为 NaNs,首先是 ffill,然后是 axis=1 上的 bfill,用于列 '1','2','3'

In [31]: df[['1','2','3']] = df[['1','2','3']].replace('', np.nan).ffill(1).bfill(1)

In [32]: df
Out[32]:
  Prod  A   1   2   3  B
0   P1  1  10  10  30  1
1   P2  1  40  60  60  2