使用以下列的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
答案 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)
如果您知道系列中的值都是0
或1
,我认为您可以使用涉及卷积的小技巧。制作一个列的副本(不一定是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