Условный подсчет со сбросом в пандах

Я пытаюсь создать столбец счетчика 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 21.03.2024 21:28

Спасибо @wjandrea за помощь в соблюдении этикета сообщества! Я надеюсь, что изменения решили проблемы, на которые вы указали.

greek_newbie 22.03.2024 17:20

Просьба улучшить существующий код лучше подходит для Code Review

CPlus 22.03.2024 21:41

@CPlus Не обязательно. Code Review предназначен для всестороннего анализа, но ОП спрашивает только о производительности, что соответствует теме Stack Overflow, хотя , вероятно, должно быть более конкретным , например, как выполнить то же самое, используя векторизованные методы Pandas. (который дает ответ Mozway). Я бы также сделал заголовок более конкретным, например: «Как мне выполнить подсчет cumcount в Pandas, но сбросить счетчик на нули?»

wjandrea 22.03.2024 22:09

Кстати, вам не нужно преобразовывать столбец в список. Просто перебирайте элементы напрямую, например def counter(bools): ... for b in bools: if b > 0: ....

wjandrea 22.03.2024 22:17
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
6
95
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете использовать 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

Другие вопросы по теме