Pandas DataFrame - 根据其他列的值填充列的 NaN

Pandas DataFrame - Fill NaNs of columns based on values of other columns

我有一个多年的宽数据框:

df = pd.DataFrame(index=pd.Index([29925, 223725, 280165, 813285, 956765], name='ID'),
                  columns=pd.Index([1991, 1992, 1993, 1994, 1995, 1996, '2010-2012'], name='Year'),
                  data = np.array([[np.NaN, np.NaN, 16, 17, 18, 19, np.NaN],
                                   [16, 17, 18, 19, 20, 21, np.NaN],
                                   [np.NaN, np.NaN, np.NaN, np.NaN, 16, 17, 31],
                                   [np.NaN, 22, 23, 24, np.NaN, 26, np.NaN],
                                   [36, 36, 37, 38, 39, 40, 55]]))

Year     1991  1992  1993  1994  1995  1996  2010-2012
ID                                                    
29925     NaN   NaN  16.0  17.0  18.0  19.0        NaN
223725   16.0  17.0  18.0  19.0  20.0  21.0        NaN
280165    NaN   NaN   NaN   NaN  16.0  17.0       31.0
813285    NaN  22.0  23.0  24.0   NaN  26.0        NaN
956765   36.0  36.0  37.0  38.0  39.0  40.0       55.0

每行的值是每个人的年龄,每个人都有一个唯一的 ID。我想根据每一行中现有的年龄值,在每一行的每一年中填充此数据框的 NaN

比如ID299251993中是16,我们知道他们在1992中是15,在1991中是14,所以我们要替换NaN 2992519921991 列中。同样,我想根据 29925 的现有年龄值替换 2010-2012 列中的 NaN。假设 2010-2012 列中的 299251996 大 15 岁。对整个数据框(即所有 ID)执行此操作的最快方法是什么?


# imports we need later
import numpy as np
import pandas as pd

这不是一个特别有效的方法,但它确实有效。我将省略您的最后一列,以使内容更加系统化。

df:

df = pd.DataFrame(index=pd.Index([29925, 223725, 280165, 813285, 956765], name='ID'),
                  columns=pd.Index([1992, 1992, 1993, 1994, 1995, 1996], name='Year'),
                  data = np.array([[np.NaN, np.NaN, 16, 17, 18, 19],
                                   [16, 17, 18, 19, 20, 21],
                                   [np.NaN, np.NaN, np.NaN, np.NaN, 16, 17],
                                   [np.NaN, 22, 23, 24, np.NaN, 26],
                                   [35, 36, 37, 38, 39, 40]]))

计算每个人的出生日期:

dob=[]
for irow, row in enumerate(df.iterrows()):
    dob.append(np.asarray([int(each) for each in df.columns]) - np.asarray(df.iloc[irow,:]))

,如果您进入列表 :

dob = [np.asarray([int(each) for each in df.columns]) - np.asarray(df.iloc[irow,:]) for irow, row in enumerate(df.iterrows())]

现在dob是这样的:

[array([  nan,   nan, 1977., 1977., 1977., 1977.]),
 array([1976., 1975., 1975., 1975., 1975., 1975.]),
 array([  nan,   nan,   nan,   nan, 1979., 1979.]),
 array([  nan, 1970., 1970., 1970.,   nan, 1970.]),
 array([1956., 1956., 1956., 1956., 1956., 1956.])]

使用 np.unique, remove nans 制作一个更简单的 Dob 列表:

dob_filtered=[np.unique(each[~np.isnan(each)])[0] for each in dob]

dob_filtered 现在看起来像这样:

[1977.0, 1975.0, 1979.0, 1970.0, 1956.0]

Attach 此列表到数据框:

df['dob']=dob_filtered

使用 dob 列填写 dfNaN

for irow, row in enumerate(df.index):
    for icol, col in enumerate(df.columns[:-2]):
        df.loc[row,col] = col - df['dob'][row]

Delete dob列(只是获取原始列而已,其他不重要):

df.drop(['dob'],axis=1)

获得:

Year    1992    1992    1993    1994    1995    1996
ID                      
29925   15.0    15.0    16.0    17.0    18.0    19.0
223725  17.0    17.0    18.0    19.0    20.0    21.0
280165  13.0    13.0    14.0    15.0    16.0    17.0
813285  22.0    22.0    23.0    24.0    25.0    26.0
956765  36.0    36.0    37.0    38.0    39.0    40.0