替换列中连续相同值后的值

Replace value after continuous same value in column

我有这样一个数据框:

df = pd.DataFrame({'A': [1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0,
                         0, 0, 0, 0, 0, 0, 1, 1]})

如果我有n个连续的(在这种情况下n = 8),下一个连续的n个之间的差距是4个零(我想设置一个规则例如:连续数字之间的差距是m <= 4 ), 如何用 1 替换这 4 个零?

我理想的输出是这样的:

df = pd.DataFrame({'A': [1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1], 'Fill_Gap': [1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0,0, 0, 0, 0, 0, 0, 1, 1]})

只有四个零(在索引 13-16 处)被 1 替换,因为它们前后有 8 个连续的 1。

如有任何建议,我们将不胜感激!

如果将列连接成字符串,则可以使用 regex。使用正则表达式,您可以使用 0{,4} 搜索 4 个或更少的零,然后使用 (?<=1{8})...(?=1{8}) 向前看 8 个零。我认为这不是一个有效的解决方案。

import re

df['fill_gap'] = df['A']
for i in re.finditer('(?<=1{8})0{,4}(?=1{8})', ''.join(df.fill_gap.astype('str'))):
    df.fill_gap.iloc[slice(*i.span())] = 1
df

输出

    A  fill_gap
0   1         1
1   1         1
2   1         1
3   0         0
4   0         0
5   1         1
6   1         1
7   1         1
8   1         1
9   1         1
10  1         1
11  1         1
12  1         1
13  0         1
14  0         1
15  0         1
16  0         1
17  1         1
18  1         1
19  1         1
20  1         1
21  1         1
22  1         1
23  1         1
24  1         1
25  0         0
26  1         1
27  1         1
28  1         1
29  0         0
30  0         0
31  0         0
32  0         0
33  0         0
34  0         0
35  0         0
36  0         0
37  0         0
38  1         1
39  1         1

这适用于任何长度的系列:

df = pd.DataFrame({'A': [1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0,
                         0, 0, 0, 0, 0, 0, 1, 1]})

#Check for runs of 8 (1's)
lst1=(df.shift(periods=0).A==1)
for x in range(1,8):
    lst1=lst1&(df.shift(periods=x).A==1)
    
#Check for runs of 4 (0's)
lst0=(df.shift(periods=0).A==0)
for x in range(1,4):
    lst0=lst0&(df.shift(periods=x).A==0)
    
#Get index
ones=np.array(list(lst1.index))[lst1]
zeros=np.array(list(lst0.index))[lst0]

#Fill Gaps
for x in list(range(1, len(ones))):
    if any(lst0[ones[x-1]:ones[x]]):
        lst1[ones[x-1]:ones[x]]=True
        
#Apply to data frame
df.loc[lst1, 'A']=1

输出:

    A
0   1
1   1
2   1
3   0
4   0
5   1
6   1
7   1
8   1
9   1
10  1
11  1
12  1
13  1
14  1
15  1
16  1
17  1
18  1
19  1
20  1
21  1
22  1
23  1
24  1
25  0
26  1
27  1
28  1
29  0
30  0
31  0
32  0
33  0
34  0
35  0
36  0
37  0
38  1
39  1