代码之家  ›  专栏  ›  技术社区  ›  Rick SilentGhost

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

  •  1
  • Rick SilentGhost  · 技术社区  · 5 年前

    我有一个看起来像这样的数据框(它表示二维空间中的区域;注意它们重叠,这是可以的):

    >>> 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和a.o.p.(6.4,5.7)不在3区之内,但在1区和2区之内。因此,应将其指定为区域2。

    0 回复  |  直到 5 年前
        1
  •  1
  •   Rick SilentGhost    5 年前

    稍微改进一下使用 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