我有一个pd.Series([-1, -1, -1, 0, 0, 0, -5, -5, 0, 0, 0, -1, -1, -1 , -1])
的熊猫系列。如何将其转换为pd.Series([-1, 0, 0, 0, -5, -5, 0, 0, 0, -1])
。
要过滤的条件是,如果-1
在一连串中大于或等于3
,则保留第一个匹配项并丢弃其余的匹配项。
由于第一个-1
的条纹是3
,因此我们保留-1
并将其余的丢弃。在第一个3
值之后,条纹消失(因为该值现在为0
)。同样,最后-1
的条纹是4
,因此我们保留-1
并丢弃其余部分。
该过滤器仅适用于-1
,-5
应该保留不变
谢谢
PS:我考虑过groupby,但是我认为它不符合我上面描述的streak
方式
答案 0 :(得分:2)
带有有条件的掩码:
In [43]: s = pd.Series([-1, -1, -1, 0, 0, 0, -5, -5, 0, 0, 0, -1, -1, -1 , -1])
In [44]: m = (s.diff() == 0) & (s.eq(-1))
In [45]: s[~m]
Out[45]:
0 -1
3 0
4 0
5 0
6 -5
7 -5
8 0
9 0
10 0
11 -1
dtype: int64
答案 1 :(得分:2)
使用一些SciPy工具-
http://example.com/foo?code=...&other_google_params=...&foo=bar
一个简单的人,希望它也能有更好的表现-
from scipy.ndimage.morphology import binary_opening,binary_erosion
def keep_first_neg1s(s, W=3):
k1 = np.ones(W,dtype=bool)
k2 = np.ones(2,dtype=bool)
m = s==-1
return s[~binary_erosion(binary_opening(m,k1),k2) | ~m]
在给定的示例def keep_first_neg1s_v2(s, W=3):
m1 = binary_opening(a==-1, np.ones(W,dtype=bool))
return s[np.r_[True,~m1[:-1]]]
上运行-
s
答案 2 :(得分:1)
IIUC,熊猫遮罩和分组方式:
def remove_streaks(T):
'''T is the threshold
'''
g = s.groupby(s.diff().ne(0).cumsum() + s.ne(-1).cumsum())
mask = g.transform('size').lt(T).cumsum() + s.diff().ne(0).cumsum()
return s.groupby(mask).first()
>>> remove_streaks(4)
[-1, -1, -1, 0, 0, 0, -5, -5, 0, 0, 0, -1]
>>> remove_streaks(3)
[-1, 0, 0, 0, -5, -5, 0, 0, 0, -1]
答案 3 :(得分:0)
创建一个布尔掩码m
,以标识值更改的位置。 Groupby
上的m.cumsum()
进行了变换,以标识具有-1
<3的组,并将其分配给掩码m1
。布尔值m or
m1和cumsum仅将数字为-1
> = 3的组分隔为相同的数字。最后,使用duplicated
进行切片。
m = s.diff().ne(0)
m1 = s.groupby(m.cumsum()).transform(lambda x: x.eq(-1).sum() < 3)
m2 = ~((m | m1).cumsum().duplicated())
s[m2]
分步:
我将您的示例修改为包括案例-1
有两个连续的行,我们应该保留。
s
Out[148]:
0 -1
1 -1
2 -1
3 0
4 -1
5 -1
6 0
7 0
8 -5
9 -5
10 0
11 0
12 0
13 -1
14 -1
15 -1
16 -1
dtype: int64
m = s.diff().ne(0)
Out[150]:
0 True
1 False
2 False
3 True
4 True
5 False
6 True
7 False
8 True
9 False
10 True
11 False
12 False
13 True
14 False
15 False
16 False
dtype: bool
m1 = s.groupby(m.cumsum()).transform(lambda x: x.eq(-1).sum() < 3)
Out[152]:
0 False
1 False
2 False
3 True
4 True
5 True
6 True
7 True
8 True
9 True
10 True
11 True
12 True
13 False
14 False
15 False
16 False
dtype: bool
m2 = ~((m | m1).cumsum().duplicated())
Out[159]:
0 True
1 False
2 False
3 True
4 True
5 True
6 True
7 True
8 True
9 True
10 True
11 True
12 True
13 True
14 False
15 False
16 False
dtype: bool
In [168]: s[m2]
Out[168]:
0 -1
3 0
4 -1
5 -1
6 0
7 0
8 -5
9 -5
10 0
11 0
12 0
13 -1
dtype: int64