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
。
比如ID29925
在1993
中是16,我们知道他们在1992
中是15,在1991
中是14,所以我们要替换NaN
29925
在 1992
和 1991
列中。同样,我想根据 29925
的现有年龄值替换 2010-2012
列中的 NaN
。假设 2010-2012
列中的 29925
比 1996
大 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
列填写 df
的 NaN
:
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
即
我有一个多年的宽数据框:
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
。
比如ID29925
在1993
中是16,我们知道他们在1992
中是15,在1991
中是14,所以我们要替换NaN
29925
在 1992
和 1991
列中。同样,我想根据 29925
的现有年龄值替换 2010-2012
列中的 NaN
。假设 2010-2012
列中的 29925
比 1996
大 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
列填写 df
的 NaN
:
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
即