2016-08-28 273 views
0

二进制数据系列有一个数据框与下面的列的条件长度:在大熊猫

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

什么是控制一些限制值“1” - 系列长度最好量化的方式?比方说,限制为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

所以要明确一点:只要有超过一定数目1组的列的多运行,要切断该以特定的数字运行并用零替换剩余的运行? –

+0

这是正确的! – Joe

回答

3

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

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

这将产生在数据帧的新列:

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 

pandas cookbook; “分组像Python的itertools.groupby”

+0

很优雅,谢谢 – Joe

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

如果你知道,在该系列中的值都将是要么0或我认为你可以用一个涉及卷积的小技巧。让你列的副本(不一定是熊猫的对象,它可以只是一个正常的numpy的阵列)

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

,并与1组成的序列比cutoff你想要的,然后再一个卷积它砍掉最后的cutoff元素。例如。为2的cutoff,你会做

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 
+0

也不错 - 谢谢 – Joe