使用Python Pandas将一个数据框中的数据按照第二个数据框定义的区间进行分组

3
我将尝试根据第二个数据框中定义的区间对第一个数据框中的数据进行分组。我认为可以通过pd.bin和pd.merge的某种组合来实现这一目标?
基本上,每个数据框目前都处于以下形式:
df = pd.DataFrame({'id':['a', 'b', 'c', 'd','e'],
                   'bin':[1, 2, 3, 3, 2],
                   'perc':[0.1,0.9,0.3,0.7,0.5]})

df2 = pd.DataFrame({'bin':[1, 1, 1, 2, 2, 2, 3, 3, 3], 
                    'result':['low', 'medium','high','low', 'medium','high','low', 'medium','high'],
                    'cut_min':[0,0.2,0.6,0,0.3,0.7,0,0.4,0.8],
                    'cut_max':[0.2,0.6,1,0.3,0.7,1,0.4,0.8,1]})

df:

bin id  perc
1   a   0.1
2   b   0.9
3   c   0.3
3   d   0.7
2   e   0.5

以下是带垃圾桶的表格,df2:

bin cut_max cut_min result
1   0.2     0.0     low
1   0.6     0.2     medium
1   1.0     0.6     high
2   0.3     0.0     low
2   0.7     0.3     medium
2   1.0     0.7     high
3   0.4     0.0     low
3   0.8     0.4     medium
3   1.0     0.8     high

我希望能够匹配bin,并使用包含df中perc值的cut_min和cut_max,在df2中找到相应的结果。因此,我希望结果表格看起来像这样:
bin id  perc    result
1   a   0.1     low
2   b   0.9     high
3   c   0.3     low
3   d   0.7     medium
2   e   0.5     medium

我最初是在SQL查询中编写了这个任务,使用join就很简单实现:

select
  df.id
  , df.bin
  , df.perc
  , df2.result
from df
inner join df2
  on df.bin = df2.bin
  and df.perc >= df2.cut_min 
  and df.perc < df2.cut_max

如果有人知道如何使用Pandas来做这件事,那将不胜感激!(而且这是我第一次在stack overflow上没能找到解决方案,如果上面的任何内容没有解释清楚,敬请谅解!)
2个回答

5

首先,在bin列上将dfdf2进行合并,然后选择cut_min <= perc < cut_max的行:(了解更多)(了解更多)

In [95]: result = pd.merge(df, df2, on='bin').query('cut_min <= perc < cut_max'); result
Out[95]: 
    bin id  perc  cut_max  cut_min  result
0     1  a   0.1      0.2      0.0     low
5     2  b   0.9      1.0      0.7    high
7     2  e   0.5      0.7      0.3  medium
9     3  c   0.3      0.4      0.0     low
13    3  d   0.7      0.8      0.4  medium

In [97]: result = result[['bin', 'id', 'perc', 'result']]

In [98]: result.sort('id')
Out[98]: 
    bin id  perc  result
0     1  a   0.1     low
5     2  b   0.9    high
9     3  c   0.3     low
13    3  d   0.7  medium
7     2  e   0.5  medium

跟进问题:如果我想像左外连接一样做怎么办?例如,如果我有一个额外的perc=1的行,我希望它报告结果为null,而不是因为不满足条件而删除该行。再次感谢! - Alex
我认为你不能使用“query”来完成此操作,因为“query”仅基于该行中包含的数据过滤每一行。因此,在“query”中无法知道某个“id”是否从未与任何查询匹配。但是,这里有两种可能的解决方案:(1)您可以向“df2”添加更多行,以涵盖所有可能的“perc”值,并将“result”设置为NaN。(2)您可以保留“df2”,并执行第二次调用“pd.merge”:“pd.merge(df,result [['id','result']],on ='id',how ='left')”。 - unutbu
第一种选择应该更快,因为它不会调用两次 pd.merge。第二种选择更容易编码。 - unutbu
1
谢谢!我最终使用了第一种替代方法(修改df2以涵盖所有可能的bin和perc值,以便我可以使用内部合并而不会丢失行)。 - Alex

0

Python中的模块bitstring提供了一种名为BitArray的类,你可以使用一个字节数组进行初始化:

(在此之前,你需要pip install bitarray

from bitstring import BitArray


BitArray(bytes = <byte_array>)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接