我有一个这样的数据帧:
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个连续的1(在这种情况下n = 8),下一个连续的n个1之间的间隔是4个0(我想建立一个规则,例如:连续数之间的间隔是m <=4),我如何用1代替这4个0 ?
我的理想输出是这样的:
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]})
只有4个0(索引13-16)被1取代,因为它们前后有8个连续的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
如果要将列连接为字符串,则可以使用正则表达式。使用regex,您可以使用0{,4}
搜索4个零或更少的零并向后看…期待8个与(?<=1{8})...(?=1{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