首页 > 解决方案 > 基于多个条件(lt、gt 测试标准)将数据帧索引作为值分配给另一个数据帧

问题描述

我有一个看起来像这样的数据框(它表示 2D 空间中的区域;请注意它们重叠,这没关系):

>>> zones = pd.DataFrame(dict(
    minx=[-10, -10, -5],
    maxx=[10, 10, 5],
    miny=[-10, 0, 0],
    maxy=[10, 10, 10],
), index=range(1,4))
>>> zones.index.name = "zone"
>>> zones
      minx  maxx  miny  maxy
zone
1      -10    10   -10    10
2      -10    10     0    10
3       -5     5     0    10

我有第二个有序对的数据框,如下所示(这里是随机数,因为它们并不重要):

>>> pairs = pd.DataFrame(list(zip((uniform(0, 10) for _ in range(10)), (uniform(0,10) for _ in range(10)))), index=range(1,11), columns=["cx", "cy"])
>>> pairs.index.name = "pair"
>>> pairs["zone"] = "??"
>>> pairs
               cx        cy zone
pair
1        8.405715  2.691102   ??
2        6.645482  1.843225   ??
3        4.123719  8.996641   ??
4        7.003991  9.695182   ??
5        7.296730  1.175356   ??
6        7.960617  9.503888   ??
7        7.694749  6.907869   ??
8        8.308742  5.439141   ??
9        6.404875  5.663983   ??
10       3.361129  3.123590   ??

我想根据第一个数据帧中的区域定义为每个 cx、cy 对填充此数据帧的“区域”系列。

我为此编写的代码如下。但是,我确信使用 pandas 有更好的方法(即,无需遍历zones列)。应该怎么做?

for num, zone in zones.transpose().iteritems():
    idx = (
        (pairs.cx.gt(zone["minx"]))
        & (pairs.cx.lt(zone["maxx"]))
        & (pairs.cy.gt(zone["miny"]))
        & (pairs.cy.lt(zone["maxy"]))
    )
    pairs.loc[idx, "zone"] = num

注意:最高的区域编号获胜。因此,例如,上面第二个表中的索引 5 具有近似的有序对 (7.3, 1.2),并且将落在区域 1、2 和 3 内。因此,它应该是区域 3。但是,索引 9 与 aop ( 6.4, 5.7) 位于 3 区之外,但在 1 区和 2 区之内。因此,应将其分配到 2 区。

标签: pythonpandasdataframe

解决方案


一点点改进使用numpy广播

cx = pairs.cx.values
cy = pairs.cy.values
minx, maxx, miny, maxy = zones.T.values
s = (
    pd.DataFrame(
        (cx > minx[:, None])
        & (cx < maxx[:, None])
        & (cy > miny[:, None])
        & (cy < maxy[:, None])
    )
    .mul(zones.index, axis=0)
    .max()
)

s
0    2
1    2
2    2
3    3
4    2
5    3
6    2
7    3
8    3
9    2
dtype: int64

pairs["zone"]=s.values

推荐阅读