Мне нужно найти количество циклов в столбце в моем фрейме данных (цикл определяется, когда переменная переходит от начального к некоторому максимальному значению и снова начинается с некоторого начального значения). Всякий раз, когда переменная имеет повторяющиеся значения, я просто усредняю их. В нужном фрейме данных я добавляю номер цикла фильтра к этому 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 строк данных, поэтому мне нужно что-то не очень медленное. Пожалуйста помоги!
Я внес изменения в вопрос. Дайте мне знать, если вам нужна дополнительная информация.

Как отметил @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
Ты был прав. Я внес изменения в вопрос. Но я все еще не получаю один и тот же номер группы для всех значений в группе.
Вы не смогли воспроизвести мои результаты с предоставленными вами образцами данных? Или проблема проявляется только с полным набором данных?
df = df.groupby(['SNo','group'],as_index = False)["VarPer"].mean().reset_index() Я внес эти изменения, и тогда все работало отлично. Спасибо!
Я пытаюсь векторизовать этот метод, так как он невероятно медленный для набора данных, содержащего ~ 77000 строк, но пока безуспешно. Может кто-нибудь подсказать, как оптимизировать мой код?
Пожалуйста, смотрите редактирование - это должно быть быстрее и лучше, потому что оно не записывает в df в цикле.
Этот подход увеличил скорость почти в 100 раз, но логика меток испортилась. Мои текущие SNo выглядят следующим образом: [1000_1,1000_2,1000_11,1000_12.....]
При редактировании мы назначаем группу на основе сгруппированного фрейма данных, но позже мы добавляем его как столбец к исходному df (не сгруппированному), что нарушает порядок столбца группы. Пожалуйста, поправьте меня, если я ошибаюсь!
Цикл перебирает группы в groupby, и, поскольку мы не используем агрегатную функцию, мы работаем со всеми строками этой группы. Взгляните, например, на df.groupby('SNo').get_group(1000). Логика работает со всеми строками, поэтому она вернет список той же длины, что и ваш фрейм данных, и не позволит вам добавить его как столбец, если он другой длины. Что касается порядка, этикетки неправильные или они просто не в порядке? Мы можем добавить нулевой отступ к суффиксу, если он сортируется неправильно — см. редактирование последней строки.
Выход для print(list(df['SNo'].unique())): ['1000_01', '1000_02', '1000_03', '1000_12', '1000_13']. Это означает, что метки неверны, верно?
Изменяет ли groupby порядок строк? Мои данные довольно последовательны, поэтому нет необходимости, чтобы функция упорядочивала их.
Да, метки определенно неверны, если между 1000_03 и 1000_12 нет ничего, но я не могу воспроизвести предоставленный вами образец. В столбце новой группы также указано 12, когда SNo равен 1000_12?
Да, в столбце новой группы также указано 12, когда SNo равен 1000_12. Я вижу, могу ли я преобразовать объект groupby в фрейм данных, чтобы я мог добавить new_grouping в качестве столбца в «фрейм данных сгруппированных по IMEI».
Думаю, нужно больше информации. Почему именно первые 6 рядов получают
_1, а последующие ряды получают_2,_3и т. д., прежде чем перезапуститься с последовательностью из трех_1? Как логика зависит от столбцовVarPerи/илиValue`? Как вы получаете максимальное и начальное значения цикла - из столбца или предопределенных?