我有两个非常大的DataFrame,它们之间的关系如下。第一个DataFrame以ID
作为索引,并指定Min
和Max
。第二个DataFrame为每个ID
提供一堆分数和价格。
对于每个ID
,我想找到与该max
的{{1}}和min scores
之间的得分相对应的平均价格。
一个例子:
ID
我想要的输出是
dt = [[1,3],[0,2],[1,3],[0,3],[1,4]]
df = pd.DataFrame(dt, columns = ['Min score','Max score'],index=[1,2,3,4,5])
dt_2 = [[1,1,10],[1,4,12],[1,3,20],[1,1,3],[2,3,2],[2,1,4],[3,1,7],[3,2,9],[3,2,3],[4,4,4],[4,2,3],[4,1,2],[5,1,1],[5,3,5],[5,5,5],[5,0,10]]
df_2 = pd.DataFrame(dt_2,columns = ['ID','score','price'])
例如,对于ID Avg
1 11
2 4
3 6.33
4 2.5
5 3
,ID=1
和min score=1
,仅价格10、20和3是相关的。这些平均值是11。
是否有内置的熊猫函数可以处理此问题?任何帮助表示赞赏。谢谢。
答案 0 :(得分:3)
将pandas.DataFrame.groupby
与Series.between
一起使用:
new_df = df_2.groupby("ID").apply(lambda x: x["price"][x["score"].between(*df.loc[x.name])].mean())
print(new_df)
输出:
ID
1 11.000000
2 4.000000
3 6.333333
4 2.500000
5 3.000000
dtype: float64
已添加:
x.name
:groupby对象的组密钥的值,即ID
中的df_2
,用作df
df.loc[x.name]
:基于来自Min Score
的{{1}}的{{1}}和Max Score
值ID
:将两个值(最小分数和最大分数)解压缩到df_2
中,以填充*df.loc[x.name]
和pandas.Series.between
参数。答案 1 :(得分:2)
您在这里:
df_3 = pd.merge(df_2, df, left_on="ID", right_index=True, how="left")
df_3[
(df_3.score >= df_3.loc[:, "Min score"]) & (df_3.score <= df_3.loc[:, "Max score"])
].groupby("ID").price.mean()
答案 2 :(得分:1)
我将通过重置索引并将其重命名为“ ID”列,然后合并两个命名为new_df的数据框,使数据框准备好进行合并:
new_df = df.reset_index().rename(columns={'index':'ID'}).merge(df_2,on='ID')
然后,我将执行以下.loc以确保您仅具有min_score和max得分:
min_max_df = new_df.loc[(new_df['score'] >= new_df['Min score'])&(new_df['score']<=new_df['Max score'])]
然后我将groupby()pandas方法与.mean()一起使用来获取平均值:
min_max_df.groupby('ID').mean()
这将导致结果:
Min score Max score score price
ID
1 1.0 3.0 1.666667 11.000000
2 0.0 2.0 1.000000 4.000000
3 1.0 3.0 1.666667 6.333333
4 0.0 3.0 1.500000 2.500000
5 1.0 4.0 2.000000 3.000000
答案 3 :(得分:1)
只需在ID
过滤器上与.loc
合并适当的行,并使用.groupby
作为均值。
dt = [[1,3],[0,2],[1,3],[0,3],[1,4]]
df = pd.DataFrame(dt, columns = ['Min score','Max score'],index=[1,2,3,4,5])
df = df.reset_index().rename({'index' : 'ID'}, axis=1)
dt_2 = [[1,1,10],[1,4,12],[1,3,20],[1,1,3],[2,3,2],[2,1,4],[3,1,7],[3,2,9],[3,2,3],[4,4,4],[4,2,3],[4,1,2],[5,1,1],[5,3,5],[5,5,5],[5,0,10]]
df_2 = pd.DataFrame(dt_2,columns = ['ID','score','price'])
df_new = pd.merge(df_2, df, how='left', on='ID')
df_final = df_new.loc[(df_new['Min score'] <= df_new['score']) & (df_new['score'] <= df_new['Max score'])]
df_final = df_final.groupby('ID')['price'].mean().reset_index().rename({'price' : 'Avg'}, axis=1)
df_final