熊猫:使用apply进行复杂过滤

时间:2016-02-18 08:13:17

标签: python pandas

让我们假设这个数据帧,我想以这样的方式过滤我从最后一个索引向后迭代,直到我找到两个连续的'a'= 0.一旦发生这种情况,其余的数据帧(包括两个零)将被过滤:

    a
1   6.5
2   0
3   0
4   4.0
5   0
6   3.2

期望的结果:

    a
4   4.0
5   0
6   3.2

我最初的想法是使用apply进行过滤,并使用shift(1) == 0 & shift(2) == 0在apply函数内,但基于此我可以单独过滤每一行,但不会在双重后的剩余行中返回false除非我使用全局变量或类似的东西,否则找到零。

任何聪明的方法吗?

3 个答案:

答案 0 :(得分:3)

您可以使用ascending=False In [89]: df[(df.sort_index(ascending=False) == 0).cumsum() < 2].dropna() Out[89]: a 4 4.0 5 0.0 6 3.2 sort_indexcumsum {/ 3}}来实现这一点:

In [99]: df.sort_index(ascending=False)
Out[99]:
     a
6  3.2
5  0.0
4  4.0
3  0.0
2  0.0
1  6.5

In [100]: df.sort_index(ascending=False) == 0
Out[100]:
       a
6  False
5   True
4  False
3   True
2   True
1  False

In [101]: (df.sort_index(ascending=False) == 0).cumsum()
Out[101]:
   a
6  0
5  1
4  1
3  2
2  3
1  3

In [103]: (df.sort_index(ascending=False) == 0).cumsum() < 2
Out[103]:
       a
6   True
5   True
4   True
3  False
2  False
1  False

In [104]: df[(df.sort_index(ascending=False) == 0).cumsum() < 2]
Out[104]:
     a
1  NaN
2  NaN
3  NaN
4  4.0
5  0.0
6  3.2

一步一步:

df_sorted = df.sort_index(ascending=False)
df[df_sorted[(pd.rolling_sum((df_sorted==0), window=2) == 2)].first_valid_index()+1:]

修改

如果您的索引从1开始,您可以使用dropnapd.rolling_sum使用类似的内容:

In [208]: df
Out[208]:
      a
1   6.5
2   0.0
3   0.0
4   7.0
5   0.0
6   0.0
7   0.0
8   4.0
9   0.0
10  0.0
11  3.2
12  5.0

df_sorted = df.sort_index(ascending=False)

In [210]: df[df_sorted[(pd.rolling_sum((df_sorted==0), window=2) == 2)].first_valid_index()+1:]
Out[210]:
      a
11  3.2
12  5.0

以@jezrael为例:

((((\d+STARTDESC))((?!STARTDESC).)*(.)((?!STARTDESC).)*((ENDDESC))))

答案 1 :(得分:2)

您可以将groupbycumcountcumsum一起使用,然后转换df并再次使用cumsum

print df
      a
1   6.5
2   0.0
3   0.0
4   7.0
5   0.0
6   0.0
7   0.0
8   4.0
9   0.0
10  0.0
11  3.2
12  5.0

print df[df.groupby((df['a'].diff(1)!=0).astype('int').cumsum()).cumcount()[::-1].cumsum()[::-1]== 0]

      a
11  3.2
12  5.0

说明:

print (df['a'].diff(1) != 0)
1      True
2      True
3     False
4      True
5      True
6     False
7     False
8      True
10     True
11     True
12     True
Name: a, dtype: bool

print  (df['a'].diff(1) != 0).astype('int') 
1     1
2     1
3     0
4     1
5     1
6     0
7     0
8     1
10    1
11    1
12    1
Name: a, dtype: int32
print  (df['a'].diff(1) != 0).astype('int') .cumsum()
1     1
2     2
3     2
4     3
5     4
6     4
7     4
8     5
10    6
11    7
12    8
Name: a, dtype: int32

print  df.groupby( (df['a'].diff(1) != 0).astype('int').cumsum() ).cumcount()
1     0
2     0
3     1
4     0
5     0
6     1
7     2
8     0
10    0
11    0
12    0
dtype: int64
print  df.groupby( (df['a'].diff(1) != 0).astype('int').cumsum() ).cumcount()[::-1].cumsum()[::-1]
1     5
2     5
3     5
4     4
5     4
6     4
7     3
8     1
10    1
11    1
11    0
12    0
dtype: int64

print  df.groupby( (df['a'].diff(1) != 0).astype('int').cumsum() ).cumcount()[::-1].cumsum()[::-1] == 0
1     False
2     False
3     False
4     False
5     False
6     False
7     False
8     False
10    False
11    False
11     True
12     True
dtype: bool

答案 2 :(得分:1)

Numpy的ediff1d功能在这里很有用

inverted = a[::-1]
index =  (numpy.ediff1d(inverted) == 0).argmax()
a[index:]