I am trying to merge Frame A to Frame B on the size asset life conditions specified in Frame B using pandas. I have tried both the merge and mergeasof commands but have not found a solution.
Frame A:
ID | Material | Size |
---|---|---|
0 | A | 9 |
1 | B | 21 |
2 | B | 14 |
Frame B: note (size specifies asset life)
Material | Size < 10 | 10 < Size < 20 | Size > 20 |
---|---|---|---|
A | 5 | 10 | 20 |
B | 1 | 5 | 10 |
To form Frame C:
ID | Material | Asset Life |
---|---|---|
0 | A | 5 |
1 | B | 10 |
2 | B | 5 |
The the first step is to normalize DataFrame B and end up with the following:
Material,LoweBound,UpperBound,AssetLife
A,0,10,5
A,10,20,10
A,20,np.Inf,20
B,0,10,1
B,10,20,5
B,20,np.Inf,10
Now a simple join should do the trick.
# step1: set_index('Material') and stack frameB dfB.columns = ['Material', 'Size <= 10', '10 < Size <= 20', 'Size > 20'] obj_size_map = dfB.set_index('Material').stack() # print(obj_size_map) # Material # A Size <= 10 5 # 10 < Size <= 20 10 # Size > 20 20 # B Size <= 10 1 # 10 < Size <= 20 5 # Size > 20 10 # dtype: int64 # step2. use pd.cut to create a size_tag for frame A, with frameB's columns as labels dfA['size_tag'] = pd.cut(dfA.Size, bins=[-np.inf, 10, 20, np.inf], labels=dfB.columns[1:]) # print(dfA) # ID Material Size size_tag # 0 0 A 9 Size <= 10 # 1 1 B 21 Size > 20 # 2 2 B 14 10 < Size <= 20 # step3. use pandas DF's index to assign a new columns dfC = dfA.set_index(['Material', 'tag']) dfC['Asset Life'] = obj_size_map # print(dfC) # ID Size size_tag Asset Life # Material tag # A Size <= 10 0 9 Size <= 10 5 # B Size > 20 1 21 Size > 20 10 # 10 < Size <= 20 2 14 10 < Size <= 20 5 # step4. output result = dfC.reset_index()[['ID', 'Material', 'Asset Life']] # print(result) # ID Material Asset Life # 0 0 A 5 # 1 1 B 10 # 2 2 B 5
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.