2016-06-21 2 views
11

У меня есть ДФ так:Определения последовательных вхождений значения

Count 
1 
0 
1 
1 
0 
0 
1 
1 
1 
0 

, и я хочу вернуть 1 в новом столбце, если есть два или более последовательные вхождения 1 в Count и 0 если нет. Таким образом, в новом столбце каждая строка получит 1 на основе этого критерия, который встречается в столбце Count. Мой желаемый результат будет таким:

Count New_Value 
1  0 
0  0 
1  1 
1  1 
0  0 
0  0 
1  1 
1  1 
1  1 
0  0 

Я имею в виду, я, возможно, придется использовать itertools, но я читал об этом и не встретилось, что мне нужно еще. Я хотел бы иметь возможность использовать этот метод для подсчета количества последовательных событий, а не только для двух. Например, иногда мне нужно подсчитать 10 последовательных явлений, я просто использую 2 в примере здесь.

+0

Проверьте, если 'df ['Count'] [1] == df ['Count'] [1] .shift (1)', и если да, '1', else' 0'. Затем вы должны '.append()' эти значения (0 или 1) в 'array'. Затем установите первый элемент ('array [0]') в '0' (по умолчанию). Затем вам нужно выяснить, как «объединить/объединить/подключить/объединить» ваш «массив» в ваш «dataframe». 100% непроверено, но я думаю, что это может сработать ... :) –

+0

Возможно, я слишком упростил свой вопрос, но если я хочу 3 последовательных события? Я не думаю, что это работает тогда –

ответ

10

Вы могли:

df['consecutive'] = df.Count.groupby((df.Count != df.Count.shift()).cumsum()).transform('size') * df.Count 

получить:

Count consecutive 
0  1   1 
1  0   0 
2  1   2 
3  1   2 
4  0   0 
5  0   0 
6  1   3 
7  1   3 
8  1   3 
9  0   0 

Отсюда вы можете , для любого порога:

threshold = 2 
df['consecutive'] = (df.consecutive > threshold).astype(int) 

, чтобы получить:

Count consecutive 
0  1   0 
1  0   0 
2  1   1 
3  1   1 
4  0   0 
5  0   0 
6  1   1 
7  1   1 
8  1   1 
9  0   0 

или, в одну стадию:

(df.Count.groupby((df.Count != df.Count.shift()).cumsum()).transform('size') * df.Count >= threshold).astype(int) 

С точки зрения эффективности, с использованием pandas методов обеспечивает существенное ускорение, когда размер проблемы возрастает:

df = pd.concat([df for _ in range(1000)]) 

%timeit (df.Count.groupby((df.Count != df.Count.shift()).cumsum()).transform('size') * df.Count >= threshold).astype(int) 
1000 loops, best of 3: 1.47 ms per loop 

по сравнению с:

%%timeit 
l = [] 
for k, g in groupby(df.Count): 
    size = sum(1 for _ in g) 
    if k == 1 and size >= 2: 
     l = l + [1]*size 
    else: 
     l = l + [0]*size  
pd.Series(l) 

10 loops, best of 3: 76.7 ms per loop 
+0

Вот один лайнер: 'df.assign (последовательный = df.Count.groupby ((df.Count! = Df.Count.shift()). Cumsum()). Transform ('size')). query ('последовательный> @threshold') ', который будет работать для любых последовательных значений (не только единиц и нулей) – MaxU

1

Не уверен, если это будет оптимизирован, но вы можете дать ему попробовать:

from itertools import groupby 
import pandas as pd 

l = [] 
for k, g in groupby(df.Count): 
    size = sum(1 for _ in g) 
    if k == 1 and size >= 2: 
     l = l + [1]*size 
    else: 
     l = l + [0]*size 

df['new_Value'] = pd.Series(l) 

df 

Count new_Value 
0 1 0 
1 0 0 
2 1 1 
3 1 1 
4 0 0 
5 0 0 
6 1 1 
7 1 1 
8 1 1 
9 0 0 
Смежные вопросы