这是post的扩展.

我的DataFrame是:

import pandas as pd
df = pd.DataFrame(
    {
        'main': ['x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'y', 'y', 'y', 'y', 'y', 'y', 'y'],
        'sub': ['c', 'c', 'c', 'd', 'd', 'e', 'e', 'e', 'e', 'f', 'f', 'f', 'f', 'g', 'g', 'g'],
        'num_1': [97, 90, 105, 2100, 1000, 101, 110, 222, 90, 100, 99, 90, 2, 92, 95, 93],
        'num_2': [100, 100, 100, 102, 102, 209, 209, 209, 209, 100, 100, 100, 100, 90, 90, 90],
        'num_3': [99, 110, 110, 110, 110, 222, 222, 222, 222, 150, 101, 200, 5, 95, 95, 100],
        'label': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p']
    }
)

这是预期输出.我想创建列result:

   main sub  num_1  num_2  num_3 label result
0     x   c     97    100     99     a      b
1     x   c     90    100    110     b      b
2     x   c    105    100    110     c      b
3     x   d   2100    102    110     d      f
4     x   d   1000    102    110     e      f
5     x   e    101    209    222     f      f
6     x   e    110    209    222     g      f
7     x   e    222    209    222     h      f
8     x   e     90    209    222     i      f
9     y   f    100    100    150     j      k
10    y   f     99    100    101     k      k
11    y   f     90    100    200     l      k
12    y   f      2    100      5     m      k
13    y   g     92     90     95     n    NaN
14    y   g     95     90     95     o    NaN
15    y   g     93     90    100     p    NaN

面具是:

mask = (
    (df.num_1 < df.num_2) & 
    (df.num_2 < df.num_3)
)

过程是这样开始的:

a) groupby列为sub

b)找到满足每个组掩码条件的第一行.

c)在结果中输入label的值

如果没有满足掩码条件的行,则groupby列更改为main以查找掩码的第一行.这一阶段有条件:

当使用main作为groupby列时,不应考虑之前的subs.

子列中的组d的上述步骤示例:

a) sub是groupby列.

b)d组中没有df.num_2df.num_1df.num_3之间的行(mask的条件)

所以现在对于组d,搜索其主组.第c章也是这个主要群体.由于它在组d之前,组c不应计入该步骤.因此,在x组中,mask的第一行有f标签(c d 222).<<

需要注意的是,对于每sub个组,num_2在整个组中不会改变.例如,对于整个组cnum_2sub.

这是我基于这answer的try ,但它不工作:

def find(g):
    # get sub as 0,1,2…
    sub = pd.factorize(g['sub'])[0]
    # convert inputs to numpy
    a = g['num_1'].to_numpy()
    b = g.loc[~g['sub'].duplicated(), 'num_2'].to_numpy()
    c = g['num_3'].to_numpy()
    # form mask
    # (a[:, None] > b) -> num_1 > num_2
    # (sub[:, None] >= np.arange(len(b))) -> exclude previous groups
    m = (a[:, None] < b) &  (a[:, None] > c) & (sub[:, None] >= np.arange(len(b)))
    # find first True per column
    return pd.Series(np.where(m.any(0), a[m.argmax(0)], np.nan)[sub],
                     index=g.index)

df['result'] = df.groupby('main', group_keys=False).apply(find)

推荐答案

你可以更新我以前的代码来使用两个比较,你必须注意使用num_2作为列.此外,您需要将输出引用列更改为"label":

def find(g):
    # get sub as 0,1,2…
    sub = pd.factorize(g['sub'])[0]
    # convert inputs to numpy
    n1 = g['num_1'].to_numpy()
    n2 = g.loc[~g['sub'].duplicated(), 'num_2'].to_numpy()
    n3 = g['num_3'].to_numpy()
    # form mask
    # (n1[:, None] > n1) -> num_1 > num_2
    # (n3[:, None] > n2) -> num_3 > num_2
    # (sub[:, None] >= np.arange(len(b))) -> exclude previous groups
    m = ((n1[:, None] < n2) & (n3[:, None] > n2)
         & (sub[:, None] >= np.arange(len(n2)))
        )
    # find first True per column
    return pd.Series(np.where(m.any(0), g['label'].to_numpy()
                              [m.argmax(0)], np.nan)[sub],
                     index=g.index)

df['result'] = df.groupby('main', group_keys=False).apply(find)

输出:

   main sub  num_1  num_2  num_3 label result
0     x   c     97    100     99     a      b
1     x   c     90    100    110     b      b
2     x   c    105    100    110     c      b
3     x   d   2100    102    110     d      f
4     x   d   1000    102    110     e      f
5     x   e    101    209    222     f      f
6     x   e    110    209    222     g      f
7     x   e    222    209    222     h      f
8     x   e     90    209    222     i      f
9     y   f    100    100    150     j      k
10    y   f     99    100    101     k      k
11    y   f     90    100    200     l      k
12    y   f      2    100      5     m      k
13    y   g     92     90     95     n    NaN
14    y   g     95     90     95     o    NaN
15    y   g     93     90    100     p    NaN

Python相关问答推荐

pandas DataFrame GroupBy.diff函数的意外输出

我从带有langchain的mongoDB中的vector serch获得一个空数组

如何使用Python将工作表从一个Excel工作簿复制粘贴到另一个工作簿?

如何让Flask 中的请求标签发挥作用

在Wayland上使用setCellWidget时,try 编辑QTable Widget中的单元格时,PyQt 6崩溃

Python,Fitting into a System of Equations

Django REST Framework:无法正确地将值注释到多对多模型,不断得到错误字段名称字段对模型无效'<><>

递归访问嵌套字典中的元素值

如何使用Numpy. stracards重新编写滚动和?

基于形状而非距离的两个numpy数组相似性

基于另一列的GROUP-BY聚合将列添加到Polars LazyFrame

如何获取Python synsets列表的第一个内容?

如何根据rame中的列值分别分组值

mdates定位器在图表中显示不存在的时间间隔

如何在信号的FFT中获得正确的频率幅值

如果服务器设置为不侦听创建,则QWebSocket客户端不连接到QWebSocketServer;如果服务器稍后开始侦听,则不连接

Scipy.linprog的可行性有问题吗?(A_ub@x0<;=b_ub).all()为True-但是-linprog(np.zeros_like(X0),A_ub=A_ub,b_ub=b_ub)不可行

用LAKEF划分实木地板AWS Wrangler

将参数从另一个python脚本中传递给main(argv

PYODBC错误(SQL包含-26272个参数标记,但提供了235872个参数,HY 000)