pandas 通过重置另一列的cummin()和条件创建新列

c90pui9n  于 11个月前  发布在  其他
关注(0)|答案(3)|浏览(74)

这是我的DataFrame:

import pandas as pd 

df = pd.DataFrame(
    {
        'a': [98, 97, 100, 135, 103, 100, 105, 109, 130],
        'b': [100, 103, 101, 105, 110, 120, 101, 150, 160]
    }
)

字符串
这是我们想要的输出。我想创建列c

a    b    c
0   98  100  100
1   97  103  100
2  100  101  100
3  135  105  100
4  103  110  110
5  100  120  110
6  105  101  101
7  109  150  150
8  130  160  150


对我来说,用纯英语描述这个问题并不容易,因为它有点复杂。cdf.b.cummmin(),但在某些条件下它会发生变化。我逐行描述它:
该过程开始于:

df['c'] = df.b.cummin()


改变c的条件是:

cond = df.a.shift(1) > df.c.shift(1)


现在重要的是那些行cond == True,对于这些行df.c = df.bbcummin()重置。
例如,cond的第一个示例是行4。所以c变为110(换句话说,无论b是什么)。对于行5,它是来自行4bcummin()。逻辑到最后都是一样的。
这是我的尝试之一。但它在cond启动时不起作用:

df['c'] = df.b.cummin()
df.loc[df.a.shift(1) > df.c.shift(1), 'c'] = df.b

a0zr77ik

a0zr77ik1#

IIUC,您可以尝试:

m1 = df["b"].le(df["a"].shift())

cm = df["b"].groupby(m1.cumsum()).cummin()

m2 = (df["b"].le(cm) | df["a"].shift().le(cm.shift()))

df["c"] = cm.where(m2, df["b"].mask(m2).cummin())

字符串
输出(* 包括中间体 *):

a    b    c    a_s     m1   cm     m2    c
0   98  100  100    NaN  False  100   True  100
1   97  103  100  98.00  False  100   True  100
2  100  101  100  97.00  False  100   True  100
3  135  105  100 100.00  False  100   True  100
4  103  110  110 135.00   True  110   True  110
5  100  120  110 103.00  False  110   True  110
6  105  101  101 100.00  False  101   True  101
7  109  150  150 105.00  False  101  False  150
8  130  160  150 109.00  False  101  False  150

[9 rows x 8 columns]

4uqofj5v

4uqofj5v2#

验证码

我找不到一种方法来进行矢量化操作。
尝试同时:

df['c'] = None
while df['c'].isna().sum() > 0: 
    df2 = df[df['c'].isna()]
    s = df2['a'].gt(df2['b'].cummin()).shift(1).fillna(0).cumsum()
    idx = df2[s.eq(0)].index
    df.loc[idx, 'c'] = df.loc[idx, 'b'].cummin()

字符串
DF

a   b   c
0   98  100 100
1   97  103 100
2   100 101 100
3   135 105 100
4   103 110 110
5   100 120 110
6   105 101 101
7   109 150 150
8   130 160 150

中间体

第一轮while

df
    a   b   c           s
0   98  100 100         0
1   97  103 100         0
2   100 101 100         0
3   135 105 100         0
4   103 110 None        1
5   100 120 None        2
6   105 101 None        2
7   109 150 None        3
8   130 160 None        4

lokaqttq

lokaqttq3#

我不知道是否有可能将其向量化,但至少在普通Python中很容易,并且它是 O(n)

# Cumulative minimum, conditionally
k = None  # For first loop
c = []
for b, a_prev in zip(df['b'], df['a'].shift()):
    if k is None or b < k or a_prev > k:
        k = b
    c.append(k)

df.assign(c=c)

个字符
如果你需要性能,you might be able to use Cython or Numba

相关问题