合并数据框并为每个项目 ID 实例添加价格数据
merge dataframes and add price data for each instance of an item ID
我正在尝试合并两个数据框,以便 DF3 中项目 ID 的每个实例显示与 DF1 中的匹配 ID 关联的定价数据。
DF3(我想要完成的)
recipeID
itemID_out
qty_out
buy_price
sell_price
buy_quantity
sell_quantity
id_1_in
qty_id1
buy_price
sell_price
buy_quantity
sell_quantity
id_2_in
qty_id2
buy_price
sell_price
buy_quantity
sell_quantity
id_3_in
qty_id3
buy_price
sell_price
buy_quantity
sell_quantity
id_4_in
qty_id4
buy_price
sell_price
buy_quantity
sell_quantity
id_5_in
qty_id5
buy_price
sell_price
buy_quantity
sell_quantity
1
1986
1
129
167
67267
21637
123
1
10
15
1500
3000
124
1
12
14
550
800
125
1
8
12
124
254
126
1
22
25
1251
890
127
1
64
72
12783
1251515
2
1987
1
1521
1675
654
1245
123
2
10
15
1500
3000
3
1988
1
128376
131429
47
23
123
10
10
15
1500
3000
124
3
12
14
550
800
这是我要合并的两个数据框。
DF1:包含26863行;项目名称、ID 和价格数据的主列表。从 API 中提取,可以添加新项目,并在用户提出更新请求后显示为新行。
itemID
name
buy_price
sell_price
buy_quantity
sell_quantity
1986
XYZ
129
167
67267
21637
123
ABC
10
15
1500
3000
124
DEF
12
14
550
800
DF2(包含 12784 行;从主列表中的项目组合的配方。从 API 中提取,可以添加新配方,并在用户更新请求后显示为新行。)
recipeID
itemID_out
qty_out
id_1_in
qty_id1
id_2_in
qty_id2
id_3_in
qty_id3
id_4_in
qty_id4
id_5_in
qty_id5
1
1986
1
123
1
124
1
125
1
126
1
127
1
2
1987
1
123
2
3
1988
1
123
10
124
3
食谱可以包含 1 到 5 个项目(出现空值)的组合,这些项目由 DF1 and/or DF2 中的 itemID_out 列的 ID 组成。
DF2 中的“id_#_in”列可以包含来自“itemID_out”列的项目 ID,因为该配方使用的是从另一个配方输出的项目。
我尝试使用以下方式合并它:
pd.merge(itemlist_modified, recipelist_modified, left_on='itemID', right_on='itemID_out')
但这只会导致单列想法按预期接收定价数据。
我觉得我正在尝试为此使用错误的功能,非常感谢任何帮助!
提前致谢!
不是一个漂亮的方法,但它首先将成分 table 融化成长格式,然后将其合并到项目列表 table
import pandas as pd
import numpy as np
itemlist_modified = pd.DataFrame({
'itemID': [1986, 123, 124],
'name': ['XYZ', 'ABC', 'DEF'],
'buy_price': [129, 10, 12],
'sell_price': [167, 15, 14],
'buy_quantity': [67267, 1500, 550],
'sell_quantity': [21637, 3000, 800],
})
recipelist_modified = pd.DataFrame({
'RecipeID': [1, 2, 3],
'itemID_out': [1986, 1987, 1988],
'qty_out': [1, 1, 1],
'id_1_in': [123, 123, 123],
'qty_id1': [1, 2, 10],
'id_2_in': [124.0, np.nan, 124.0],
'qty_id2': [1.0, np.nan, 3.0],
'id_3_in': [125.0, np.nan, np.nan],
'qty_id3': [1.0, np.nan, np.nan],
'id_4_in': [126.0, np.nan, np.nan],
'qty_id4': [1.0, np.nan, np.nan],
'id_5_in': [127.0, np.nan, np.nan],
'qty_id5': [1.0, np.nan, np.nan],
})
#columns which are not qty or input id cols
id_vars = ['RecipeID','itemID_out','qty_out']
#prepare dict to map column name to ingredient number
col_renames = {}
col_renames.update({'id_{}_in'.format(i+1):'ingr_{}'.format(i+1) for i in range(5)})
col_renames.update({'qty_id{}'.format(i+1):'ingr_{}'.format(i+1) for i in range(5)})
#melt reciplist into longform
long_recipelist = recipelist_modified.melt(
id_vars=id_vars,
var_name='ingredient',
).dropna()
#add a new column to specify whether each row is a qty or an id
long_recipelist['kind'] = np.where(long_recipelist['ingredient'].str.contains('qty'),'qty_in','id_in')
#convert ingredient names
long_recipelist['ingredient'] = long_recipelist['ingredient'].map(col_renames)
#pivot on the new ingredient column
reshape_recipe_list = long_recipelist.pivot(
index=['RecipeID','itemID_out','qty_out','ingredient'],
columns='kind',
values='value',
).reset_index()
#merge with the itemlist
priced_ingredients = pd.merge(reshape_recipe_list, itemlist_modified, left_on='id_in', right_on='itemID')
#pivot on the priced ingredients
priced_ingredients = priced_ingredients.pivot(
index = ['RecipeID','itemID_out','qty_out'],
columns = 'ingredient',
)
#flatten the hierarchical columns
priced_ingredients.columns = ["_".join(a[::-1]) for a in priced_ingredients.columns.to_flat_index()]
priced_ingredients.columns.name = ''
priced_ingredients = priced_ingredients.reset_index()
priced_ingredients
部分输出:
我正在尝试合并两个数据框,以便 DF3 中项目 ID 的每个实例显示与 DF1 中的匹配 ID 关联的定价数据。
DF3(我想要完成的)
recipeID | itemID_out | qty_out | buy_price | sell_price | buy_quantity | sell_quantity | id_1_in | qty_id1 | buy_price | sell_price | buy_quantity | sell_quantity | id_2_in | qty_id2 | buy_price | sell_price | buy_quantity | sell_quantity | id_3_in | qty_id3 | buy_price | sell_price | buy_quantity | sell_quantity | id_4_in | qty_id4 | buy_price | sell_price | buy_quantity | sell_quantity | id_5_in | qty_id5 | buy_price | sell_price | buy_quantity | sell_quantity |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1986 | 1 | 129 | 167 | 67267 | 21637 | 123 | 1 | 10 | 15 | 1500 | 3000 | 124 | 1 | 12 | 14 | 550 | 800 | 125 | 1 | 8 | 12 | 124 | 254 | 126 | 1 | 22 | 25 | 1251 | 890 | 127 | 1 | 64 | 72 | 12783 | 1251515 |
2 | 1987 | 1 | 1521 | 1675 | 654 | 1245 | 123 | 2 | 10 | 15 | 1500 | 3000 | ||||||||||||||||||||||||
3 | 1988 | 1 | 128376 | 131429 | 47 | 23 | 123 | 10 | 10 | 15 | 1500 | 3000 | 124 | 3 | 12 | 14 | 550 | 800 |
这是我要合并的两个数据框。
DF1:包含26863行;项目名称、ID 和价格数据的主列表。从 API 中提取,可以添加新项目,并在用户提出更新请求后显示为新行。
itemID | name | buy_price | sell_price | buy_quantity | sell_quantity |
---|---|---|---|---|---|
1986 | XYZ | 129 | 167 | 67267 | 21637 |
123 | ABC | 10 | 15 | 1500 | 3000 |
124 | DEF | 12 | 14 | 550 | 800 |
DF2(包含 12784 行;从主列表中的项目组合的配方。从 API 中提取,可以添加新配方,并在用户更新请求后显示为新行。)
recipeID | itemID_out | qty_out | id_1_in | qty_id1 | id_2_in | qty_id2 | id_3_in | qty_id3 | id_4_in | qty_id4 | id_5_in | qty_id5 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1986 | 1 | 123 | 1 | 124 | 1 | 125 | 1 | 126 | 1 | 127 | 1 |
2 | 1987 | 1 | 123 | 2 | ||||||||
3 | 1988 | 1 | 123 | 10 | 124 | 3 |
食谱可以包含 1 到 5 个项目(出现空值)的组合,这些项目由 DF1 and/or DF2 中的 itemID_out 列的 ID 组成。
DF2 中的“id_#_in”列可以包含来自“itemID_out”列的项目 ID,因为该配方使用的是从另一个配方输出的项目。
我尝试使用以下方式合并它:
pd.merge(itemlist_modified, recipelist_modified, left_on='itemID', right_on='itemID_out')
但这只会导致单列想法按预期接收定价数据。
我觉得我正在尝试为此使用错误的功能,非常感谢任何帮助!
提前致谢!
不是一个漂亮的方法,但它首先将成分 table 融化成长格式,然后将其合并到项目列表 table
import pandas as pd
import numpy as np
itemlist_modified = pd.DataFrame({
'itemID': [1986, 123, 124],
'name': ['XYZ', 'ABC', 'DEF'],
'buy_price': [129, 10, 12],
'sell_price': [167, 15, 14],
'buy_quantity': [67267, 1500, 550],
'sell_quantity': [21637, 3000, 800],
})
recipelist_modified = pd.DataFrame({
'RecipeID': [1, 2, 3],
'itemID_out': [1986, 1987, 1988],
'qty_out': [1, 1, 1],
'id_1_in': [123, 123, 123],
'qty_id1': [1, 2, 10],
'id_2_in': [124.0, np.nan, 124.0],
'qty_id2': [1.0, np.nan, 3.0],
'id_3_in': [125.0, np.nan, np.nan],
'qty_id3': [1.0, np.nan, np.nan],
'id_4_in': [126.0, np.nan, np.nan],
'qty_id4': [1.0, np.nan, np.nan],
'id_5_in': [127.0, np.nan, np.nan],
'qty_id5': [1.0, np.nan, np.nan],
})
#columns which are not qty or input id cols
id_vars = ['RecipeID','itemID_out','qty_out']
#prepare dict to map column name to ingredient number
col_renames = {}
col_renames.update({'id_{}_in'.format(i+1):'ingr_{}'.format(i+1) for i in range(5)})
col_renames.update({'qty_id{}'.format(i+1):'ingr_{}'.format(i+1) for i in range(5)})
#melt reciplist into longform
long_recipelist = recipelist_modified.melt(
id_vars=id_vars,
var_name='ingredient',
).dropna()
#add a new column to specify whether each row is a qty or an id
long_recipelist['kind'] = np.where(long_recipelist['ingredient'].str.contains('qty'),'qty_in','id_in')
#convert ingredient names
long_recipelist['ingredient'] = long_recipelist['ingredient'].map(col_renames)
#pivot on the new ingredient column
reshape_recipe_list = long_recipelist.pivot(
index=['RecipeID','itemID_out','qty_out','ingredient'],
columns='kind',
values='value',
).reset_index()
#merge with the itemlist
priced_ingredients = pd.merge(reshape_recipe_list, itemlist_modified, left_on='id_in', right_on='itemID')
#pivot on the priced ingredients
priced_ingredients = priced_ingredients.pivot(
index = ['RecipeID','itemID_out','qty_out'],
columns = 'ingredient',
)
#flatten the hierarchical columns
priced_ingredients.columns = ["_".join(a[::-1]) for a in priced_ingredients.columns.to_flat_index()]
priced_ingredients.columns.name = ''
priced_ingredients = priced_ingredients.reset_index()
priced_ingredients
部分输出: