循环遍历 2 个数据帧并采用特定列的模式
Looping through 2 dataframes and take mode of specific columns
给定的是 df1(其中包含每个商店销售最多和最少的产品):
id most_sold_A most_sold_B most_sold_C least_sold_A least_sold_B least_sold_C
1 1 0 0 0 1 1
2 0 1 0 1 0 0
3 0 1 1 1 0 0
并且df2(包含2个店铺之间的距离)也给出了:
id1 id2 distance
1 2 0.5
1 3 3.0
2 3 0.2
生成的数据帧应该
- 检查哪些 shop_ids 在每个 shopid 的 1k 距离内
- 采用most_sold_product模式,1k以内压倒所有参赛者
- 取least_sold_product模式1k以内的所有参赛者
结果 df:
id most_sold_A most_sold_B most_sold_C least_sold_A least_sold_B least_sold_C /
1 1 0 0 0 1 1
2 0 1 0 1 0 0
3 0 1 1 1 0 0
most_sold_competition_within_1k least_sold_competition_within_1k
B A
[A,B,C] [A,B,C]
B A
编辑
df1 = pd.DataFrame([[1,1,0,0,0,1,1],
[2,0,1,0,1,0,0],
[3,0,1,1,1,0,0]],columns = ["id","most_sold_A","most_sold_B","most_sold_C","least_sold_A","least_sold_B","least_sold_C"])
df2 = pd.DataFrame([[1,2,0.5],
[1,3,3.0],
[2,3,0.2]], columns = ["id1","id2","distance"])
似乎“棘手”的部分是为每家商店找到相关的竞争对手。我敢肯定还有更多优雅的解决方案,但 straight-forward 一个是:
def find_competitors(x, df2):
shops = np.unique(df2[(df2.id1==x.id) | (df2.id2 == x.id)][['id1','id2']])
competitors = np.delete(shops, np.argwhere(shops == x.id))
return competitors
df2 = df2[df2.distance<=1]
df1['competitors'] = df1.apply(lambda x: find_competitors(x, df2),axis=1)
现在,对于每家商店,您现在是相关的竞争对手,您可以通过简单地遍历每家商店的竞争对手来找到其他 2 个问题的答案(竞争对手的销量最高和销量最低的产品)。我希望已经足够清楚了。
更新
为了找到竞争对手least/most的产品,您可以使用:
most_cols = [col for col in df1.columns if 'most' in col]
def find_competitors_by_metric(x, metric_cols):
competitors_metric = df1[df1.id.isin(x.competitors)][metric_cols]
return competitors_metric.T[competitors_metric.any()].T.columns
most_for_competitors = df1.apply(lambda x: find_competitors_by_metric(x,most_cols),axis=1)
现在您可以向该函数发送您想为商店的竞争对手计算哪些指标(假设这些指标存在于数据框中)。
我想出了一些东西,但我认为它可以进一步优化。这个想法是首先过滤范围内的竞争对手,然后加入,然后用 .apply()
:
计算结果
import numpy as np
import pandas as pd
df1 = pd.DataFrame([[1,1,0,0,0,1,1],
[2,0,1,0,1,0,0],
[3,0,1,1,1,0,0]],columns = ["id","most_sold_A","most_sold_B","most_sold_C","least_sold_A","least_sold_B","least_sold_C"])
df2 = pd.DataFrame([[1,2,0.5],
[1,3,3.0],
[2,3,0.2]], columns = ["id1","id2","distance"])
df2 = pd.concat([df2,df2[["id2","id1","distance"]].rename(columns = {"id2":"id1","id1":"id2"})]).reset_index()[["id1","id2","distance"]]
df2["id2"] = df2["id2"].astype(str)
df2 = df2[df2["distance"]<1][["id1","id2"]].groupby("id1").agg({'id2': ','.join}).reset_index()
df3 = pd.merge(df1,df2,how = 'left',left_on="id", right_on="id1")
most_cols = [col for col in df3.columns if 'most' in col]
least_cols = [col for col in df3.columns if 'least' in col]
df3["most_sold_competition_within_1k"] = df3.apply(lambda x: [df3[df3["id"]==int(elem)][most_cols].columns[[df3[df3["id"]==int(elem)][most_cols].values == 1][0][0]] for elem in x["id2"].split(",")],axis = 1)
df3["least_sold_competition_within_1k"] = df3.apply(lambda x: [df3[df3["id"]==int(elem)][least_cols].columns[[df3[df3["id"]==int(elem)][least_cols].values == 1][0][0]] for elem in x["id2"].split(",")],axis = 1)
df3 = df3[["id"]+most_cols+least_cols+["most_sold_competition_within_1k","least_sold_competition_within_1k"]]
df3
输出:
id most_sold_A most_sold_B most_sold_C least_sold_A least_sold_B least_sold_C most_sold_competition_within_1k least_sold_competition_within_1k
0 1 1 0 0 0 1 1 [[most_sold_B]] [[least_sold_A]]
1 2 0 1 0 1 0 0 [[most_sold_B, most_sold_C], [most_sold_A] [[least_sold_A], [least_sold_B, least_sold_C]]
2 3 0 1 1 1 0 0 [[most_sold_B]] [[least_sold_A]]
给定的是 df1(其中包含每个商店销售最多和最少的产品):
id most_sold_A most_sold_B most_sold_C least_sold_A least_sold_B least_sold_C
1 1 0 0 0 1 1
2 0 1 0 1 0 0
3 0 1 1 1 0 0
并且df2(包含2个店铺之间的距离)也给出了:
id1 id2 distance
1 2 0.5
1 3 3.0
2 3 0.2
生成的数据帧应该
- 检查哪些 shop_ids 在每个 shopid 的 1k 距离内
- 采用most_sold_product模式,1k以内压倒所有参赛者
- 取least_sold_product模式1k以内的所有参赛者
结果 df:
id most_sold_A most_sold_B most_sold_C least_sold_A least_sold_B least_sold_C /
1 1 0 0 0 1 1
2 0 1 0 1 0 0
3 0 1 1 1 0 0
most_sold_competition_within_1k least_sold_competition_within_1k
B A
[A,B,C] [A,B,C]
B A
编辑
df1 = pd.DataFrame([[1,1,0,0,0,1,1],
[2,0,1,0,1,0,0],
[3,0,1,1,1,0,0]],columns = ["id","most_sold_A","most_sold_B","most_sold_C","least_sold_A","least_sold_B","least_sold_C"])
df2 = pd.DataFrame([[1,2,0.5],
[1,3,3.0],
[2,3,0.2]], columns = ["id1","id2","distance"])
似乎“棘手”的部分是为每家商店找到相关的竞争对手。我敢肯定还有更多优雅的解决方案,但 straight-forward 一个是:
def find_competitors(x, df2):
shops = np.unique(df2[(df2.id1==x.id) | (df2.id2 == x.id)][['id1','id2']])
competitors = np.delete(shops, np.argwhere(shops == x.id))
return competitors
df2 = df2[df2.distance<=1]
df1['competitors'] = df1.apply(lambda x: find_competitors(x, df2),axis=1)
现在,对于每家商店,您现在是相关的竞争对手,您可以通过简单地遍历每家商店的竞争对手来找到其他 2 个问题的答案(竞争对手的销量最高和销量最低的产品)。我希望已经足够清楚了。
更新
为了找到竞争对手least/most的产品,您可以使用:
most_cols = [col for col in df1.columns if 'most' in col]
def find_competitors_by_metric(x, metric_cols):
competitors_metric = df1[df1.id.isin(x.competitors)][metric_cols]
return competitors_metric.T[competitors_metric.any()].T.columns
most_for_competitors = df1.apply(lambda x: find_competitors_by_metric(x,most_cols),axis=1)
现在您可以向该函数发送您想为商店的竞争对手计算哪些指标(假设这些指标存在于数据框中)。
我想出了一些东西,但我认为它可以进一步优化。这个想法是首先过滤范围内的竞争对手,然后加入,然后用 .apply()
:
import numpy as np
import pandas as pd
df1 = pd.DataFrame([[1,1,0,0,0,1,1],
[2,0,1,0,1,0,0],
[3,0,1,1,1,0,0]],columns = ["id","most_sold_A","most_sold_B","most_sold_C","least_sold_A","least_sold_B","least_sold_C"])
df2 = pd.DataFrame([[1,2,0.5],
[1,3,3.0],
[2,3,0.2]], columns = ["id1","id2","distance"])
df2 = pd.concat([df2,df2[["id2","id1","distance"]].rename(columns = {"id2":"id1","id1":"id2"})]).reset_index()[["id1","id2","distance"]]
df2["id2"] = df2["id2"].astype(str)
df2 = df2[df2["distance"]<1][["id1","id2"]].groupby("id1").agg({'id2': ','.join}).reset_index()
df3 = pd.merge(df1,df2,how = 'left',left_on="id", right_on="id1")
most_cols = [col for col in df3.columns if 'most' in col]
least_cols = [col for col in df3.columns if 'least' in col]
df3["most_sold_competition_within_1k"] = df3.apply(lambda x: [df3[df3["id"]==int(elem)][most_cols].columns[[df3[df3["id"]==int(elem)][most_cols].values == 1][0][0]] for elem in x["id2"].split(",")],axis = 1)
df3["least_sold_competition_within_1k"] = df3.apply(lambda x: [df3[df3["id"]==int(elem)][least_cols].columns[[df3[df3["id"]==int(elem)][least_cols].values == 1][0][0]] for elem in x["id2"].split(",")],axis = 1)
df3 = df3[["id"]+most_cols+least_cols+["most_sold_competition_within_1k","least_sold_competition_within_1k"]]
df3
输出:
id most_sold_A most_sold_B most_sold_C least_sold_A least_sold_B least_sold_C most_sold_competition_within_1k least_sold_competition_within_1k
0 1 1 0 0 0 1 1 [[most_sold_B]] [[least_sold_A]]
1 2 0 1 0 1 0 0 [[most_sold_B, most_sold_C], [most_sold_A] [[least_sold_A], [least_sold_B, least_sold_C]]
2 3 0 1 1 1 0 0 [[most_sold_B]] [[least_sold_A]]