我需要优化代码的帮助,因为我的解决方案非常慢。
我有2个数据框。一列6列-包含主要项目的1列和包含建议项目的5列。第二个df包含每个订单的销售数据(每个产品在单独的行中)。
我需要检查哪些产品被标记为“主要”产品,推荐哪些产品,哪些只是其他产品。如果订购的主要产品超过1个,我需要重复该订单,并且每个重复只设置1个主要产品。
我尝试使用pandas并找到了可行的解决方案,但是我使用了itertuples,将dfs按主要项目拆分,等等。这给出了我正确的结果,但是1个订单正在计算将近2秒钟,而我拥有的订单超过100万。
promo = pd.DataFrame({'main_id':[2,4,6],
'recommended_1':[1,2,8],
'recommended_2':[8,6,9],
'recommended_3':[10,9,10],
'recommended_4': [12,11,11],
'recommended_5': [6,7,8]})
orders = pd.DataFrame({
'order':['a','a','a','b','b','b','c','c'],
'product':[1,2,3,2,4,9,6,9]
})
promo['recommended_list'] = promo[
['recommended_1','recommended_2',
'recommended_3','recommended_4',
'recommended_5']].values.tolist()
flag = pd.DataFrame(
{'flag':orders['product'].isin(promo.main_id)}
)
flaged_orders = pd.concat([orders,flag], axis=1)
main_in_orders = pd.DataFrame(
flaged_orders.query("flag").groupby(['order'])['product']
.agg(lambda x: x.tolist())
)
order_holder = pd.DataFrame()
for index, row in main_in_orders.itertuples():
for item in row:
working_order = orders.query("order==@index")
working_order.loc[working_order['product']==item,'kategoria']='M'
recommended_products = promo.loc[promo['main_id']==item]['recommended_list'].iloc[0]
working_order.loc[working_order['product'].isin(recommended_products), 'kategoria'] = 'R'
working_order['main_id'] = item
order_holder = pd.concat([order_holder, working_order])
# NaN values in this case would be "additional items"
print(order_holder)
那么,你能帮我更快的选择吗?将我指向某个方向会很棒,因为我已经坚持了一段时间。熊猫是可选的。
您可以执行两项操作merge
以拥有所需的所有行,然后用于np.select
创建“ kategoria”列。第一种merge
方法是使用方法仅在“产品”列中保留具有“ main_id”的行inner
,然后第二种方法merge
是使用相同的“订单”为多个“ main_id”创建重复项left
。
df_mainid = orders.merge(promo, left_on='product', right_on='main_id', how='inner')
print (df_mainid)
# order product main_id recommended_1 recommended_2 recommended_3 \
# 0 a 2 2 1 8 10
# 1 b 2 2 1 8 10
# 2 b 4 4 2 6 9
# 3 c 6 6 8 9 10
#
# recommended_4 recommended_5
# 0 12 6
# 1 12 6
# 2 11 7
# 3 11 8
因此,您只会在“产品”中获得带有“ main_id”的行,然后
df_merged = orders.merge(df_mainid.drop('product', axis=1), on=['order'], how='left')\
.sort_values(['order', 'main_id'])
print (df_merged)
# order product main_id recommended_1 recommended_2 recommended_3 \
# 0 a 1 2 1 8 10
# 1 a 2 2 1 8 10
# 2 a 3 2 1 8 10
# 3 b 2 2 1 8 10
# 5 b 4 2 1 8 10
# 7 b 9 2 1 8 10
# 4 b 2 4 2 6 9
# 6 b 4 4 2 6 9
# 8 b 9 4 2 6 9
# 9 c 6 6 8 9 10
# 10 c 9 6 8 9 10
# recommended_4 recommended_5
# 0 12 6
# 1 12 6
# 2 12 6
# 3 12 6
# 5 12 6
# 7 12 6
# 4 11 7
# 6 11 7
# 8 11 7
# 9 11 8
# 10 11 8
如果有多个“ main_id”,则会得到重复的“订单”。最后,使用创建列“ kategoria” np.select
。第一个条件是,如果“产品”等于“ main_id”,然后是“ M”,第二个条件是,如果“产品”位于以“推荐”开头的其他列中,则是“ R”。最后,drop
建议使用的列获得与相同的输出order_holder
。
conds = [ df_merged['product'].eq(df_merged.main_id) ,
(df_merged['product'][:,None] == (df_merged.filter(like='recommended'))).any(1) ]
choices = ['M', 'R']
df_merged['kategoria'] = np.select( conds , choices , np.nan)
df_merged = df_merged.drop(df_merged.filter(like='recommended').columns, axis=1)
print (df_merged)
order product main_id kategoria
0 a 1 2 R
1 a 2 2 M
2 a 3 2 nan
3 b 2 2 M
5 b 4 2 nan
7 b 9 2 nan
4 b 2 4 R
6 b 4 4 M
8 b 9 4 R
9 c 6 6 M
10 c 9 6 R
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句