在 pandas 中删除超过指定长度的重复序列
remove sequences of duplicates longer than a specified length in pandas
假设我有一个 pandas 系列,其中包含一些重复序列,例如像这样:
pd.Series([
1,2,3,0,0,4,5,6,0,0,0,0,7,1,1,1,8,9,0,10
])
我的目标是找到一种简单的方法,用 nan 删除/替换所有长度超过所选长度 L 的重复序列。例如,如果 L=3,该系列将如下所示:
pd.Series([
1,2,3,0,0,4,5,6,nan,nan,nan,nan,7,nan,nan,nan,8,9,0,10
])
(或删除 nan)。
此外,更改代码以始终保留重复项的第一个元素会很有趣:
pd.Series([
1,2,3,0,0,4,5,6,0,nan,nan,nan,7,1,nan,nan,8,9,0,10
])
下一个挑战是让此代码针对沿轴 = 0 的 DataFrame 高效工作。
谢谢!
最好的,JZ
通过将累积和的移位值与助手 g
系列进行比较来创建连续的组,然后通过 Series.map
with Series.value_counts
and compare by Series.ge
for greater or equal, add missing values by mask by Series.mask
:
对值进行计数
g = s.ne(s.shift()).cumsum()
s = s.mask(g.map(g.value_counts()).ge(3))
print (s)
0 1.0
1 2.0
2 3.0
3 0.0
4 0.0
5 4.0
6 5.0
7 6.0
8 NaN
9 NaN
10 NaN
11 NaN
12 7.0
13 NaN
14 NaN
15 NaN
16 8.0
17 9.0
18 0.0
19 10.0
dtype: float64
第一个副本的替代解决方案是按位 AND
:
通过 &
链接 Series.duplicated
s = s.mask(g.map(g.value_counts()).ge(3) & g.duplicated())
print (s)
0 1.0
1 2.0
2 3.0
3 0.0
4 0.0
5 4.0
6 5.0
7 6.0
8 0.0
9 NaN
10 NaN
11 NaN
12 7.0
13 1.0
14 NaN
15 NaN
16 8.0
17 9.0
18 0.0
19 10.0
dtype: float64
多列解决方案已更改:
cols = ['a','b','c']
f = lambda x: x.map(x.value_counts())
df1 = df.mask(df[cols].ne(df[cols].shift()).cumsum().apply(f).ge(3))
print (df1)
a b c
0 1.0 1.0 1.0
1 2.0 2.0 2.0
2 3.0 3.0 3.0
3 0.0 0.0 0.0
4 0.0 0.0 0.0
5 4.0 4.0 4.0
6 5.0 5.0 5.0
7 6.0 6.0 6.0
8 NaN NaN NaN
9 NaN NaN NaN
10 NaN NaN NaN
11 NaN NaN NaN
12 7.0 7.0 7.0
13 NaN NaN NaN
14 NaN NaN NaN
15 NaN NaN NaN
16 8.0 8.0 8.0
17 9.0 9.0 9.0
18 0.0 0.0 0.0
19 10.0 10.0 10.0
第二个解决方案:
cols = ['a','b','c']
f = lambda x: x.map(x.value_counts()).ge(3) & x.duplicated()
df1 = df.mask(df[cols].ne(df[cols].shift()).cumsum().apply(f))
假设我有一个 pandas 系列,其中包含一些重复序列,例如像这样:
pd.Series([
1,2,3,0,0,4,5,6,0,0,0,0,7,1,1,1,8,9,0,10
])
我的目标是找到一种简单的方法,用 nan 删除/替换所有长度超过所选长度 L 的重复序列。例如,如果 L=3,该系列将如下所示:
pd.Series([
1,2,3,0,0,4,5,6,nan,nan,nan,nan,7,nan,nan,nan,8,9,0,10
])
(或删除 nan)。
此外,更改代码以始终保留重复项的第一个元素会很有趣:
pd.Series([
1,2,3,0,0,4,5,6,0,nan,nan,nan,7,1,nan,nan,8,9,0,10
])
下一个挑战是让此代码针对沿轴 = 0 的 DataFrame 高效工作。
谢谢!
最好的,JZ
通过将累积和的移位值与助手 g
系列进行比较来创建连续的组,然后通过 Series.map
with Series.value_counts
and compare by Series.ge
for greater or equal, add missing values by mask by Series.mask
:
g = s.ne(s.shift()).cumsum()
s = s.mask(g.map(g.value_counts()).ge(3))
print (s)
0 1.0
1 2.0
2 3.0
3 0.0
4 0.0
5 4.0
6 5.0
7 6.0
8 NaN
9 NaN
10 NaN
11 NaN
12 7.0
13 NaN
14 NaN
15 NaN
16 8.0
17 9.0
18 0.0
19 10.0
dtype: float64
第一个副本的替代解决方案是按位 AND
:
&
链接 Series.duplicated
s = s.mask(g.map(g.value_counts()).ge(3) & g.duplicated())
print (s)
0 1.0
1 2.0
2 3.0
3 0.0
4 0.0
5 4.0
6 5.0
7 6.0
8 0.0
9 NaN
10 NaN
11 NaN
12 7.0
13 1.0
14 NaN
15 NaN
16 8.0
17 9.0
18 0.0
19 10.0
dtype: float64
多列解决方案已更改:
cols = ['a','b','c']
f = lambda x: x.map(x.value_counts())
df1 = df.mask(df[cols].ne(df[cols].shift()).cumsum().apply(f).ge(3))
print (df1)
a b c
0 1.0 1.0 1.0
1 2.0 2.0 2.0
2 3.0 3.0 3.0
3 0.0 0.0 0.0
4 0.0 0.0 0.0
5 4.0 4.0 4.0
6 5.0 5.0 5.0
7 6.0 6.0 6.0
8 NaN NaN NaN
9 NaN NaN NaN
10 NaN NaN NaN
11 NaN NaN NaN
12 7.0 7.0 7.0
13 NaN NaN NaN
14 NaN NaN NaN
15 NaN NaN NaN
16 8.0 8.0 8.0
17 9.0 9.0 9.0
18 0.0 0.0 0.0
19 10.0 10.0 10.0
第二个解决方案:
cols = ['a','b','c']
f = lambda x: x.map(x.value_counts()).ge(3) & x.duplicated()
df1 = df.mask(df[cols].ne(df[cols].shift()).cumsum().apply(f))