我有一个巨大的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")