Pandas

时间:2016-08-28 09:04:09

标签: python pandas dataframe vectorization

使用以下列的DataFrame:

df['A'] = [1,1,1,0,1,1,1,1,0,1]

通过某种限制值控制" 1" -series长度的最佳矢量化方法是什么?我们说限制是2,然后生成的列' B'必须看起来像:

   A  B
0  1  1
1  1  1
2  1  0
3  0  0
4  1  1
5  1  1
6  1  0
7  1  0
8  0  0
9  1  1

3 个答案:

答案 0 :(得分:3)

一个完全向量化的解决方案是使用shift - groupby - cumsum - cumcount组合 1 来指示连续运行的位置短于2(或您喜欢的任何限制值)。然后,&这个新的布尔系列与原始列:

df['B'] = ((df.groupby((df.A != df.A.shift()).cumsum()).cumcount() <= 1) & df.A)\
          .astype(int) # cast the boolean Series back to integers

这将在DataFrame中生成新列:

   A  B
0  1  1
1  1  1
2  1  0
3  0  0
4  1  1
5  1  1
6  1  0
7  1  0
8  0  0
9  1  1

1 pandas cookbook;关于分组的部分,&#34;分组像Python的itertools.groupby&#34;

答案 1 :(得分:2)

另一种方式(检查前两个是否为1):

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

In [444]: limit = 2

In [445]: df['B'] = map(lambda x: df['A'][x] if x < limit else int(not all(y == 1 for y in df['A'][x - limit:x])), range(len(df)))

In [446]: df
Out[446]: 
   A  B
0  1  1
1  1  1
2  1  0
3  0  0
4  1  1
5  1  1
6  1  0
7  1  0
8  0  0
9  1  1

答案 2 :(得分:2)

如果您知道系列中的值都是01,我认为您可以使用涉及卷积的小技巧。制作一个列的副本(不一定是Pandas对象,它可以只是一个普通的Numpy数组)

a = df['A'].as_matrix()

并将其与1个序列进行卷积,该序列比您想要的cutoff长一个,然后删除最后cutoff个元素。例如。对于cutoff的2,你会做

long_run_count = numpy.convolve(a, [1, 1, 1])[:-2]

在这种情况下,结果数组给出了在该元素之前和之前包含的3个元素中出现的1个数。如果该数字为3,那么您处于超过长度2的运行中。因此,只需将这些元素设置为零。

a[long_run_count > 2] = 0

您现在可以将结果数组分配到DataFrame

中的新列
df['B'] = a

将此转换为更通用的方法:

def trim_runs(array, cutoff):
    a = numpy.asarray(array)
    a[numpy.convolve(a, numpy.ones(cutoff + 1))[:-cutoff] > cutoff] = 0
    return a