首页 > 解决方案 > 如何使用熊猫区间查找值,填充另一个数据框

问题描述

我有两个数据框(df1, df2):

x  id  
35  4   
55  3
92  2
99  5

id  x               val
1   (0.0, 50.0]     1.2
2   (90.0, inf]     0.5
3   (0.0, 50.0]     8.9
3  (50.0, 90.0]     9.9
4   (0.0, 50.0]     4.3
4  (50.0, 90.0]     1.1
4   (90.0, inf]     2.9
5  (50.0, 90.0]     3.2
5   (90.0, inf]     5.1

想要x_new在第一个数据帧中添加一个新列,df1,其值取决于第二个数据帧的查找表,df2。根据id和 的值x,有一个特殊的乘数,得到新的值x_new

  x  id   x_new
 35  4    35*4.3
 55  3    55*9.9 
 92  2    ...
 99  5    ...

第二个数据框中的值范围是使用 pandas cut 创建的:

df2 = df.groupby(['id', pd.cut(df.x, [0,50,90,np.inf])]).apply(lambda x: np.average(x['var1']/x['var2'], weights=x['var1'])).reset_index(name='val')

我的想法是从内置查找功能的 pandas 开始:

df1['x_new'] = df.lookup(df.index, df['id'])

不知道如何让它工作。

另请参阅我之前的问题以获取有关代码的更多信息。

标签: pythonpython-3.xpandasdataframelookup

解决方案


  • 可以在 a 中找到一个值pd.Interval
    • 40 in pd.Interval(0.0, 50.0, closed='right')评估为True
  • 同样,如果 apd.Interval在索引中,则使用 , 传递的值.loc将找到正确的间隔。
    • df2.loc[(3, 35)]将返回8.9
    • 由于df2是多索引的,因此索引的值作为tuple.
    • 如果的索引中不存在KeyErrorfrom 的值,则会出现A ,因此您可能需要使用 编写函数。 df1df2try-except
      • df1_in_df2 = df1[df1.id.isin(df2.index.get_level_values(0))]df1.id会发现一切df2.index
import pandas as pd
import numpy as np

# setupt dataframes
df1 = pd.DataFrame({'id': [4, 3, 2, 5], 'x': [35, 55, 92, 99]})
df2 = pd.DataFrame({'id': [1, 2, 3, 3, 4, 4, 4, 5, 5], 'x': [pd.Interval(0.0, 50.0, closed='right'), pd.Interval(90.0, np.inf, closed='right'), pd.Interval(0.0, 50.0, closed='right'), pd.Interval(50.0, 90.0, closed='right'), pd.Interval(0.0, 50.0, closed='right'), pd.Interval(50.0, 90.0, closed='right'), pd.Interval(90.0, np.inf, closed='right'), pd.Interval(50.0, 90.0, closed='right'), pd.Interval(90.0, np.inf, closed='right')], 'val': [1.2, 0.5, 8.9, 9.9, 4.3, 1.1, 2.9, 3.2, 5.1]})

# set id and x as the index of df2
df2 = df2.set_index(['id', 'x'])

# display(df2)
                 val
id x                
1  (0.0, 50.0]   1.2
2  (90.0, inf]   0.5
3  (0.0, 50.0]   8.9
   (50.0, 90.0]  9.9
4  (0.0, 50.0]   4.3
   (50.0, 90.0]  1.1
   (90.0, inf]   2.9
5  (50.0, 90.0]  3.2
   (90.0, inf]   5.1

# use a lambda expression to pass id and x of df1 as index labels to df2 and return val
df1['val'] = df1.apply(lambda x: df2.loc[(x['id'], x['x'])], axis=1)

# multiple x and val to get x_new
df1['x_new'] = df1.x.mul(df1.val)

# display(df1)
   id   x  val  x_new
0   4  35  4.3  150.5
1   3  55  9.9  544.5
2   2  92  0.5   46.0
3   5  99  5.1  504.9

推荐阅读