根据其他行的多个列有条件地填充pandas中的空白



我有一个巨大的df,在品牌列中缺少条目,需要根据其他行填充。如果所有其他3列都匹配,则用现有品牌填充空白,否则填写"其他"。如果这是我的起始df:

df_start = pd.DataFrame({'device_id':[1,1,1,1,2,2,3,3,3,3,4,4,4,4],
'head':['a','a','b','b','a','b','a','b','b','b','a','b','c','d'],
'supplement':['Salt','Salt','Pepper','Pepper','Pepper','Pepper','Salt','Pepper','Salt','Pepper','Pepper','Salt','Pepper','Salt'],
'brand':['white',np.nan,np.nan,'white','white','black',np.nan,np.nan,'white','black',np.nan,'white','black',np.nan]})

如何得到这个结果:

df_end = pd.DataFrame({'device_id':[1,1,1,1,2,2,3,3,3,3,4,4,4,4],
'head':['a','a','b','b','a','b','a','b','b','b','a','b','c','d'],
'supplement':['Salt','Salt','Pepper','Pepper','Pepper','Pepper','Salt','Pepper','Salt','Pepper','Pepper','Salt','Pepper','Salt'],
'brand':['white','white','white','white','white','black','Other','black','white','black','Other','white','black','Other']})

您可以尝试在需要相同的列上使用groupby,在您的情况下'device_id', 'head', 'supplement',并使用向前填充ffill(),向后填充bfill(),并在最后使用'其他'fillna(),因为剩菜将是那些在这3列中没有相同行的:

result = df_start.groupby(['device_id','head','supplement'])
.apply(lambda x: x.ffill().bfill().fillna('Other'))

打印:

>>> result
device_id head supplement  brand
0           1    a       Salt  white
1           1    a       Salt  white
2           1    b     Pepper  white
3           1    b     Pepper  white
4           2    a     Pepper  white
5           2    b     Pepper  black
6           3    a       Salt  Other
7           3    b     Pepper  black
8           3    b       Salt  white
9           3    b     Pepper  black
10          4    a     Pepper  Other
11          4    b       Salt  white
12          4    c     Pepper  black
13          4    d       Salt  Other

基于简单映射的不需要组by(昂贵)的解决方案。

from collections import defaultdict
# create a mapping (ddict with key ('device_id', 'head', 'supplement')
# returns 'Other' when missing key
mapping = defaultdict(lambda: 'Other')
mapping.update(df_start.dropna()
.set_index(['device_id', 'head', 'supplement'])['brand']
.to_dict())
# apply function using the mapping to get the brand
brand = df_start.iloc[:, :-1].apply(lambda row: mapping[tuple(row)], axis=1)

可以在创建完数据框后替换brands列中的nan值。这可能不是最有效的方法,但却是最简单的方法。

df['brand'].replace(np.NaN, "Other")

相关内容

  • 没有找到相关文章