Я пытаюсь создать столбец счетчика cum, который подсчитывает экземпляры логической переменной, но сбрасывается до нуля, когда он встречает ноль в логической переменной. Я ищу условный cumcount.
Я опубликовал свой код (он работает) первоначального удара по этой проблеме. Тем не менее, я хочу посмотреть, есть ли у кого-нибудь что-нибудь более эффективное, поскольку цикл, используемый в моем решении, может быть медленным в больших файлах dfs.
def counter(series_converted_to_a_list):
counter = 0
counter_list = []
# loop through the list and count
for i in range(len(series_converted_to_a_list)):
if series_converted_to_a_list[i] > 0:
counter += 1
else:
counter = 0
counter_list.append(counter)
return counter_list
# Sample dataframe
df = pd.DataFrame({'bool': [1,0,1,1,1,1,1,0,1,1,1,0,0,1,1,1]})
# convert the boolean column to a list
bool_series_converted_to_a_list = list(df['bool'])
# use the function
counter_list = counter(bool_series_converted_to_a_list)
# convert the list into a column in the sample dataframe
df['counter_list'] = counter_list
df
Что вы пробовали? Например, знаете ли вы, как получить последовательные группы?
Спасибо @wjandrea за помощь в соблюдении этикета сообщества! Я надеюсь, что изменения решили проблемы, на которые вы указали.
Просьба улучшить существующий код лучше подходит для Code Review
@CPlus Не обязательно. Code Review предназначен для всестороннего анализа, но ОП спрашивает только о производительности, что соответствует теме Stack Overflow, хотя , вероятно, должно быть более конкретным , например, как выполнить то же самое, используя векторизованные методы Pandas. (который дает ответ Mozway). Я бы также сделал заголовок более конкретным, например: «Как мне выполнить подсчет cumcount в Pandas, но сбросить счетчик на нули?»
Кстати, вам не нужно преобразовывать столбец в список. Просто перебирайте элементы напрямую, например def counter(bools): ... for b in bools: if b > 0: ....






Вы можете использовать groupby.cumcount после маскировки 0 и установки пользовательского группировщика для всех групп, начинающихся с 0, и, наконец, восстановления 0 с помощью переиндексации:
df = pd.DataFrame({'bool': [1,0,1,1,1,1,1,0,1,1,1,0,0,1,1,1]})
m = df['bool'].eq(1)
df['cumcount'] = (m[m].groupby((~m).cumsum()).cumcount().add(1)
.reindex(df.index, fill_value=0)
)
Или, может быть, проще, используя cumsum, который гарантирует, что 1 всегда начинается с первого 1 в группе:
m = df['bool'].eq(1)
df['cumcount'] = m.groupby((~m).cumsum()).cumsum()
Выход:
bool cumcount
0 1 1
1 0 0
2 1 1
3 1 2
4 1 3
5 1 4
6 1 5
7 0 0
8 1 1
9 1 2
10 1 3
11 0 0
12 0 0
13 1 1
14 1 2
15 1 3
Я создал df, похожий на ваш ввод, и построил следующее:
import pandas as pd
Data = {'booleanvar': ['1','0','1','0','1','1','1']}
df = pd.DataFrame(Data)
df
for idx, entry in df.iterrows():
if idx == 0:
if entry['booleanvar'] == '0':
df.loc[idx , 'result'] = '0'
if entry['booleanvar'] == '1':
df.loc[idx , 'result'] = '1'
if idx > 0:
if entry['booleanvar'] == '0':
df.loc[idx , 'result'] = '0'
if entry['booleanvar'] == '1':
df.loc[idx , 'result'] = int(df.loc[idx-1 , 'result']) + 1
df
Выход:
booleanvar result
0 1 1
1 0 0
2 1 1
3 0 0
4 1 1
5 1 2
6 1 3