В учебной последовательности шесть строк: A, A, B, A, A, C. Если превратить размеры соседних серий в словарь с ключом-кодом, сумма его значений окажется равна четырём: ранняя серия A будет заменена поздней. Строки не исчезли из исходного файла: ошибочным оказался переход от соседних серий к общим частотам. Разберём, что возвращает itertools.groupby и как проверить, на какой вопрос отвечает результат.

Буквы ниже обозначают вымышленные коды категорий, а не идентификаторы реальных участников. Код выполнен в Python 3.12.14 без внешних пакетов; использована официальная документация ветви 3.12. Считаем строки по категориям, не число уникальных людей и не число независимых наблюдений.

Соседняя серия и общая частота — разные задачи

Согласно документации itertools.groupby, новая группа начинается при изменении ключа. Функция не собирает автоматически все одинаковые коды из разных мест последовательности. В нашем порядке две пары A разделены строкой B, поэтому получатся две отдельные серии A.

  Строка исходного файла       Код категории  
  r1       A  
  r2       A  
  r3       B  
  r4       A  
  r5       A  
  r6       C  
Авторская схема, не интерфейс. Данные и условия учебные, вымышленные. groupby: серии или итоги?. Исходный порядок A, A, B, A, A, C 6 строк; серии: A/2, B/1, A/2, C/1. Словарь по сериям A: 2; B: 1; C: 1 Последняя A заменила первую. Сумма 4. Общие частоты A: 4; B: 1; C: 1 После sorted-копии; сумма 6. Коды вымышлены. Исходный порядок сохранен.
Авторская схема, не интерфейс. Данные и условия учебные, вымышленные. groupby: серии или итоги?. Исходный порядок A, A, B, A, A, C 6 строк; серии: A/2, B/1, A/2, C/1. Словарь по сериям A: 2; B: 1; C: 1 Последняя A заменила первую. Сумма 4. Общие частоты A: 4; B: 1; C: 1 После sorted-копии; сумма 6. Коды вымышлены. Исходный порядок сохранен.

Для исследования последовательности такой результат полезен: видны длины непрерывных серий. Если требуется общее количество строк каждой категории, нужно другое представление. Нельзя называть две серии A двумя разными категориями только потому, что они расположены отдельно.

Полный пример: четыре серии, но три категории

runs хранит списки строк каждой серии, run_sizes хранит их длины. last_run_only намеренно показывает ошибочное сворачивание серий в словарь, а totals даёт общий подсчёт после сортировки копии. Исходный список codes сохраняет прежний порядок.

from itertools import groupby

codes = ["A", "A", "B", "A", "A", "C"]
runs = [(key, list(group)) for key, group in groupby(codes)]
run_sizes = [(key, len(group)) for key, group in runs]
last_run_only = {key: len(group) for key, group in runs}
totals = {key: len(list(group)) for key, group in groupby(sorted(codes))}
print("runs =", run_sizes)
print("last_run_only =", last_run_only)
print("sum_last_run_only =", sum(last_run_only.values()))
print("totals =", totals)
print("sum_totals =", sum(totals.values()))
print("original =", codes)
assert run_sizes == [("A", 2), ("B", 1), ("A", 2), ("C", 1)]
assert last_run_only == {"A": 2, "B": 1, "C": 1}
assert sum(last_run_only.values()) == 4
assert totals == {"A": 4, "B": 1, "C": 1}
assert sum(totals.values()) == len(codes) == 6
assert codes == ["A", "A", "B", "A", "A", "C"]
runs = [('A', 2), ('B', 1), ('A', 2), ('C', 1)]
last_run_only = {'A': 2, 'B': 1, 'C': 1}
sum_last_run_only = 4
totals = {'A': 4, 'B': 1, 'C': 1}
sum_totals = 6
original = ['A', 'A', 'B', 'A', 'A', 'C']

Получены серии A/2, B/1, A/2, C/1. В словаре last_run_only повторный ключ A получает значение последней серии: 2, а не сумму 4. Это свойство словаря Python, а не автоматическое суммирование groupby. Поэтому сумма значений ошибочного словаря равна 2 + 1 + 1 = 4 при шести исходных строках.

После sorted(codes) одинаковые коды стоят рядом. В totals получаем A: 4, B: 1, C: 1; сумма равна 6. Здесь сортируется новый список, а не сам codes. Проверки assert сверяют обе промежуточные структуры и итог, а не только число в последней строке.

Когда сортировка поможет, а когда изменит смысл

  Вопрос читателя       Подход к этому примеру  
  Каковы длины серий в порядке файла?       Сохранить исходный порядок и немедленно материализовать каждую группу.  
  Сколько всего строк каждой категории?       Для показанных строковых кодов сгруппировать отсортированную копию по тому же ключу.  
  Нужно ли удалить повторные строки?       Эта программа не отвечает на вопрос о дубликатах и ничего не удаляет.  

Если порядок отражает время или последовательность событий, сортировка по категории уничтожает информацию о расположении серий в этой рабочей копии. Не подменяйте один вопрос другим. Для сложных записей явно задайте одну и ту же функцию ключа при сортировке и группировке; возможность сортировки и смысл ключа нужно проверить для своих типов данных.

Группа, которую возвращает groupby, сама является итератором и разделяет источник с внешним итератором. Если значения нужны позже, сохраните list(group) во время обхода, как в примере. Простое сохранение списка пар из ключа и итератора без чтения групп не равнозначно сохранению всех элементов: продвижение внешнего итератора влияет на доступность предыдущей группы.

Проверка перед переносом в свою работу

  • Сформулируйте задачу: соседние серии или общие частоты; укажите единицу подсчёта.
  • Сохраните исходный порядок отдельно и зафиксируйте, какую копию сортировали.
  • Сверьте сумму частот с числом включённых строк и проверьте повторные ключи при создании словаря.
  • При подсчёте по записям определите ключ до запуска. Пропуски, неодинаковые типы и конфликтные значения требуют отдельной проверки.

Шесть кодов достаточны для демонстрации поведения программы, но не для вывода о реальных группах. Этот фрагмент не читает CSV, не проверяет схему файла и не различает копию записи и повторный визит. Отдельно разобрано, как отличить дубликат от повторного наблюдения: там нужен смысл ключей, а здесь проверяется операция группировки последовательности.

Если после проверки структуры нужна консультация по обработке своего набора, можно обсудить помощь со статистическим анализом. Подготовьте исходный файл, описание категорий и точный вопрос: одинаковые счетчики сами по себе не подтверждают корректность исследовательского вывода.