我有一个数据框 df1:
id age val
10 2 10
20 3 NaN
30 4 55
40 5 NaN
我有另一个数据框 df2:
age val_main
1 111
2 222
3 333
4 444
5 555
6 666
我只想将 df1 中的 NaN 值替换为 df2 中的相应值。
我正在寻找的最终输出是:
id age val
10 2 10
20 3 333
30 4 55
40 5 555
我尝试通过 for 循环迭代 df1,然后从 df2 中找到 df1 中的行为空的值。
例如:
for index,row in df1.iterrows():
if row['val'].isnull():
df2.loc[df2.age==row.age].val
.....
.....
但我正在寻找一种更强大、更智能的方法来做到这一点。
最佳答案
使用Series.map
通过字典 Series.fillna
:
d = dict(zip(df2['age'], df2['val_main']))
#alternative with Series
#d = df2.set_index('age')['val_main']
df1['val'] = df1['val'].fillna(df1['age'].map(d))
print (df1)
id age val
0 10 2 10.0
1 20 3 333.0
2 30 4 55.0
3 40 5 555.0
性能取决于两个数据帧中的行数以及唯一值的数量和缺失值的数量:
np.random.seed(123)
N = 1000000
df2 = pd.DataFrame({'age': np.arange(1,101),
'val_main':np.random.randint(1000, size=100)})
print (df2)
df1 = pd.DataFrame({'id': np.random.randint(1000, size=N),
'age':np.random.randint(100, size=N),
'val':np.random.choice([10,20,30,np.nan], size=N)})
print (df1)
In [229]: %%timeit
...: df = df1.merge(df2, on = 'age', how='left')
...: df['val'] = df.val.fillna(df.pop('val_main'))
...:
172 ms ± 3.82 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [230]: %%timeit d = dict(zip(df2['age'], df2['val_main']))
...: #alternative with Series
...: #d = df2.set_index('age')['val_main']
...: df1['val'] = df1['val'].fillna(df1['age'].map(d))
...:
40 ms ± 145 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
关于python - 如果值为空,则从另一个数据框 pandas 更改数据框的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54628948/