Как выполнять вложенные групповые операции в фрейме данных на основе условия в столбце?

Мне нужно найти количество циклов в столбце в моем фрейме данных (цикл определяется, когда переменная переходит от начального к некоторому максимальному значению и снова начинается с некоторого начального значения). Всякий раз, когда переменная имеет повторяющиеся значения, я просто усредняю ​​их. В нужном фрейме данных я добавляю номер цикла фильтра к этому SNo в качестве суффикса, чтобы узнать, в каком цикле находится данный SNo. Мне нужно получить минимальное и максимальное значение для данного цикла и SNo (это не предопределено)

Пример фрейма данных и желаемого фрейма данных:

SNo  VarPer Value
1000    0   1.2
1000    1   2.2
1000    2   3.2
1000    3   4.2
1000    4   5.2
1000    4   6.2
1000    5   7.2
1000    5   8.2
1000    0   0.9
1000    1   1.9
1000    2   2.9
1000    3   3.9
1000    3   4.9
1000    4   5.9
1001    0   0.5
1001    1   1.5
1001    2   2.5
1001    2   3.5
1001    0   1
1001    1   1
1001    2   1
SNo   VarPer Value
1000_1  0   1.2
1000_1  1   2.2
1000_1  2   3.2
1000_1  3   4.2
1000_1  4   5.7
1000_1  5   7.7
1000_2  0   0.9
1000_2  1   1.9
1000_2  2   2.9
1000_2  3   4.4
1000_2  4   5.9
1001_1  0   0.5
1001_1  1   1.5
1001_1  2   3
1001_2  0   1
1001_2  1   1
1001_2  2   1

Я уже пробовал следующее:

y = dat.groupby(['SNo','VarPer'], as_index=False)['Value'].mean()

Но это группировка всего без учета циклов. У меня около 70000 строк данных, поэтому мне нужно что-то не очень медленное. Пожалуйста помоги!

Думаю, нужно больше информации. Почему именно первые 6 рядов получают _1, а последующие ряды получают _2, _3 и т. д., прежде чем перезапуститься с последовательностью из трех _1? Как логика зависит от столбцов VarPer и/или Value`? Как вы получаете максимальное и начальное значения цикла - из столбца или предопределенных?

Peter Leimbigler 28.05.2019 22:59

Я внес изменения в вопрос. Дайте мне знать, если вам нужна дополнительная информация.

Pratyusha Pasumarty 29.05.2019 15:16
1
2
83
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Как отметил @Peter Leimbigler, мне также не совсем понятна логика создания суффикса. Я думаю, что от 1000_3 до 1000_6 все должны быть 1000_2.

Чтобы использовать groupby, вам нужно будет создать новую группу примерно так:

for _, values in df.groupby('SNo'):
    group_label = 0
    for row in values.index:
        if df.loc[row, 'VarPer'] !=0:
            df.loc[row, 'group'] = group_label
        else:
            group_label+=1
            df.loc[row, 'group'] = group_label

EDIT: вам, вероятно, не следует использовать цикл для записи непосредственно в фрейм данных. Вместо этого вы можете создать список, а затем создать новый столбец, используя этот список. Это будет быстрее.

new_grouping = []
for _, values in df.groupby('SNo'):
    label = 0
    group = []
    for row in values.index:
        if df.loc[row, 'VarPer'] !=0:
            group.append(label)
        else:
            label+=1
            group.append(label)
    new_grouping.extend(group)
df['group'] = new_grouping

Это будет не быстро, но, возможно, вы (или кто-то другой) сможете его векторизовать. Затем вы можете использовать groupby для получения усредненных значений:

df = df.groupby(['SNo','group'],as_index = False])["VarPer"].mean().reset_index()

Если ваши суффиксы на самом деле должны быть такими, как я описал выше, вы можете сделать:

df['SNo'] = df['SNo'].map(str) +'_' + df['group'].map(lambda x: str(int(x)).zfill(2))

Это даст вам:

SNo  group VarPer Value
1000_1  1.0 0   1.2
1000_1  1.0 1   2.2
1000_1  1.0 2   3.2
1000_1  1.0 3   4.2
1000_1  1.0 4   5.7
1000_1  1.0 5   7.7
1000_2  2.0 0   0.9
1000_2  2.0 1   1.9
1000_2  2.0 2   2.9
1000_2  2.0 3   4.4
1000_2  2.0 4   5.9
1001_1  1.0 0   0.5
1001_1  1.0 1   1.5
1001_1  1.0 2   3.0
1001_2  2.0 0   1.0
1001_2  2.0 1   1.0
1001_2  2.0 2   1.0

Ты был прав. Я внес изменения в вопрос. Но я все еще не получаю один и тот же номер группы для всех значений в группе.

Pratyusha Pasumarty 29.05.2019 22:53

Вы не смогли воспроизвести мои результаты с предоставленными вами образцами данных? Или проблема проявляется только с полным набором данных?

seanswe 29.05.2019 23:46
df = df.groupby(['SNo','group'],as_index = False)["VarPer"].mean().reset_index() Я внес эти изменения, и тогда все работало отлично. Спасибо!
Pratyusha Pasumarty 30.05.2019 16:34

Я пытаюсь векторизовать этот метод, так как он невероятно медленный для набора данных, содержащего ~ 77000 строк, но пока безуспешно. Может кто-нибудь подсказать, как оптимизировать мой код?

Pratyusha Pasumarty 24.06.2019 20:12

Пожалуйста, смотрите редактирование - это должно быть быстрее и лучше, потому что оно не записывает в df в цикле.

seanswe 24.06.2019 23:45

Этот подход увеличил скорость почти в 100 раз, но логика меток испортилась. Мои текущие SNo выглядят следующим образом: [1000_1,1000_2,1000_11,1000_12.....]

Pratyusha Pasumarty 25.06.2019 16:13

При редактировании мы назначаем группу на основе сгруппированного фрейма данных, но позже мы добавляем его как столбец к исходному df (не сгруппированному), что нарушает порядок столбца группы. Пожалуйста, поправьте меня, если я ошибаюсь!

Pratyusha Pasumarty 26.06.2019 16:06

Цикл перебирает группы в groupby, и, поскольку мы не используем агрегатную функцию, мы работаем со всеми строками этой группы. Взгляните, например, на df.groupby('SNo').get_group(1000). Логика работает со всеми строками, поэтому она вернет список той же длины, что и ваш фрейм данных, и не позволит вам добавить его как столбец, если он другой длины. Что касается порядка, этикетки неправильные или они просто не в порядке? Мы можем добавить нулевой отступ к суффиксу, если он сортируется неправильно — см. редактирование последней строки.

seanswe 26.06.2019 16:58

Выход для print(list(df['SNo'].unique())): ['1000_01', '1000_02', '1000_03', '1000_12', '1000_13']. Это означает, что метки неверны, верно?

Pratyusha Pasumarty 26.06.2019 17:09

Изменяет ли groupby порядок строк? Мои данные довольно последовательны, поэтому нет необходимости, чтобы функция упорядочивала их.

Pratyusha Pasumarty 26.06.2019 17:11

Да, метки определенно неверны, если между 1000_03 и 1000_12 нет ничего, но я не могу воспроизвести предоставленный вами образец. В столбце новой группы также указано 12, когда SNo равен 1000_12?

seanswe 26.06.2019 18:12

Да, в столбце новой группы также указано 12, когда SNo равен 1000_12. Я вижу, могу ли я преобразовать объект groupby в фрейм данных, чтобы я мог добавить new_grouping в качестве столбца в «фрейм данных сгруппированных по IMEI».

Pratyusha Pasumarty 26.06.2019 18:22

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