如何标记特定列中值更改之前和之后的 2 行?

问题描述 投票:0回答:2

我想在数据框中创建一个新列“标记”。 当“数字”列中的值发生更改时,我已经将“标记”的值设置为 True。 我想在“数字”列中的值更改之前和之后的两行设置“True”上的值。

我想看:

数字 标记
10 错误
10 错误
10 错误
10 错误
10 正确
10 正确
20 正确
20 正确
20 错误
20 错误
20 正确
20 正确
30 正确
40 正确
40 正确
40 错误
40 错误
40 错误

到目前为止发现了什么:

import pandas as pd
data = [10,10,10,10,10,10,20,20,20,20,20,20,20,30,40,40,40,40,40] 
df = pd.DataFrame(data, columns=['Numbers'])
check=10
def detect_changes (row):
    global check 
    if row['Numbers'] == check :           
        return False
    else :
        check=check+10
        return True
df['mark']=df.apply (lambda row: detect_changes(row), axis=1)
python pandas
2个回答
2
投票

您可以使用滚动最大值:

# better than the used function
df['mark'] = df['Numbers'].diff().eq(10)

N = 2 # number of rows before/after 
df['mark2'] = df['mark'].rolling(2*N+1, min_periods=1, center=True).max().astype(bool)

输出:

    Numbers   mark  mark2
0        10  False  False
1        10  False  False
2        10  False  False
3        10  False  False
4        10  False   True
5        10  False   True
6        20   True   True
7        20  False   True
8        20  False   True
9        20  False  False
10       20  False  False
11       20  False   True
12       20  False   True
13       30   True   True
14       40   True   True
15       40  False   True
16       40  False   True
17       40  False  False
18       40  False  False

1 前,2 后

# better than the used function
df['mark'] = df['Numbers'].diff().eq(10)

# 1 before
m1 = df.loc[::-1, 'mark'].rolling(1+1, min_periods=1).max().astype(bool)

# 2 after
m2 = df['mark'].rolling(2+1, min_periods=1).max().astype(bool)

df['mark2'] = m1|m2

输出:

    Numbers   mark  mark2
0        10  False  False
1        10  False  False
2        10  False  False
3        10  False  False
4        10  False  False
5        10  False   True
6        20   True   True
7        20  False   True
8        20  False   True
9        20  False  False
10       20  False  False
11       20  False   True
12       30   True   True
13       40   True   True
14       40  False   True
15       40  False   True
16       40  False  False
17       40  False  False

0
投票
def function1(ss:pd.Series):
    if ss.iloc[1]!=ss.iloc[2]:
        df1.loc[ss.index,'mark']=True
    return 0

df1.rolling(4).apply(function1)
df1.fillna(False)


   Numbers   mark
0        10  False
1        10  False
2        10  False
3        10  False
4        10   True
5        10   True
6        20   True
7        20   True
8        20  False
9        20  False
10       20   True
11       20   True
12       30   True

另一个,使用duckdb:

(
df1.sql.select("*,lead(Numbers,1) over(order by index) col1,lead(Numbers,2) over(order by index) col2")
.select("*,max(col1!=col2) over(order by index rows between 3 preceding and current row) mark")
.order("index")
)
© www.soinside.com 2019 - 2024. All rights reserved.