Given two dataframes which you may download from this link:
df1:
category category_id big_class big_class_id small_class small_class_id
0 A 1 a1 11 aa1 111
1 A 1 a2 12 aa2 112
2 B 2 b1 21 bb1 221
3 B 2 b2 22 bb2 222
4 B 2 b3 23 bb3 223
df2:
item small_class small_class_id ... big_class_id category category_id
0 aaa1 aa1 111.0 ... 12.0 B 2.0
1 aaa2 aa2 112.0 ... 11.0 NaN NaN
2 bbb3 NaN NaN ... NaN B 2.0
3 bbb4 bb3 223.0 ... NaN A 1.0
4 bbb1 NaN NaN ... 23.0 A 1.0
You can find data in df2 doesn't follow the hierarchic order of df1, which means ['small_class', 'small_class_id', 'big_class', 'big_class_id', 'category', 'category_id'] ie., for row of aaa1, its small_class is aa1, then, big_class and category should be a1 and A, instead of a2 and B based on df1, same logic for row of bbb1 in df2, if its big_class is b2 then category should be B instead of A.
My trial code:
df = pd.merge(df2, df1, on = 'small_class', how = 'left')
df['category'] = df['category_y'].fillna(df['category_x'])
df['big_class'] = df['big_class_y'].fillna(df['big_class_x'])
df.drop(['big_class_x', 'category_x', 'category_y',
'big_class_y'], axis=1, inplace=True)
df3 = pd.merge(df, df1[['big_class', 'category']], on = 'big_class', how = 'left')
df3['category'] = df3['category_y'].fillna(df3['category_x'])
df3.drop(['category_y', 'category_x'], axis=1, inplace=True)
Any ideas how could acheive this in more concise way? Thanks.
The expected result:
item small_class small_class_id ... big_class_id category category_id
0 aaa1 aa1 111.0 ... 11.0 A 1
1 aaa2 aa2 112.0 ... 12.0 A 1
2 bbb3 NaN NaN ... NaN B 2
3 bbb4 bb3 223.0 ... 23.0 B 2
4 bbb1 NaN NaN ... 22.0 B 2