Группировка похожих элементов в Pandas

#python #pandas #group-by #aggregation

#python #pandas #группировать по #агрегация

Вопрос:

Я пытаюсь что-то сделать, и мне интересно, можно ли это сделать в Pandas или есть инструмент получше для этой работы (в настоящее время я просто использую для этого обычный python). Вот исходные данные:

 # We have a listing of files for the movie Titanic
# And we want to break them into groups of similar titles,
# To see which of those are possible duplicates.
import pandas as pd
titanic_files = [
    {"File": "Titanic_HD2398.mov",  "Resolution": "HD", "FrameRate": 23.98, "Runtime": 102},
    {"File": "Titanic1.mov",        "Resolution": "SD", "FrameRate": 23.98, "Runtime": 102},
    {"File": "Titanic1.mov",        "Resolution": "HD", "FrameRate": 23.98, "Runtime": 102},
    {"File": "Titanic.mov",         "Resolution": "HD", "FrameRate": 24.00, "Runtime": 103},
    {"File": "MY_HD2398.mov",       "Resolution": "HD", "FrameRate": 23.98, "Runtime": 102}
]
df = pd.DataFrame(titanic_files)
  

И я хочу сгруппировать эти файлы по похожим данным, никогда не сворачивая данные на уровне строк, например:

  1. Шаг 1 — Группировка по разрешению

     
    ---- HD ----
    File               Resolution             FrameRate              RunTime
    Titanic_HD2398.mov HD                     23.98                  102
    Titanic1.mov       HD                     23.98                  102
    Titanic.mov        HD                     24.00                  103
    MY_HD2398.mov      HD                     23.98                  102
    
    ---- SD ----
    File               Resolution             FrameRate              RunTime
    Titanic1.mov       SD                     23.98                  102
      
  2. Шаг 2 — Группировка по частоте кадров

     ---- HD -----------------------
      ----------- 23.98 ------------
    File               Resolution             FrameRate              RunTime
    Titanic_HD2398.mov HD                     23.98                  102
    Titanic1.mov       HD                     23.98                  102
    MY_HD2398.mov      HD                     23.98                  102
    
      ----------- 24.00 ------------
    File               Resolution             FrameRate              RunTime
    Titanic.mov        HD                     24.00                  103
    
    
    ---- SD -----------------------
       ---------- 23.98 ------------
    
    File               Resolution             FrameRate              RunTime
    Titanic1.mov       SD                     23.98                  102
      

И, в конце концов, я хочу в основном иметь отдельные фреймы данных для каждой из наименьших групп. В python я в настоящее время делаю это со следующей структурой данных:

 {
   'GroupingKeys': [{File1WithinThatBucket}, {File2WithinThatBucket}, ...]
}
  

Например:

 {
   'HD 23.98'   [{'File': ...}],
   'HD 24.00'   [{'File': ...}]
}
  

Также, пожалуйста, имейте в виду, что существует около 10-15 полей, по которым я группирую, я только что включил два в приведенный выше вопрос, поэтому этот подход должен быть довольно обобщенным (кроме того, некоторые критерии соответствия не точны, например, время выполнения может быть привязано к чему-то вроде / — 2 секунд, некоторые значения могут быть нулевыми и т.д.).

И вернемся к первоначальному вопросу: можно ли что-то подобное сделать в Pandas, и если да, то как?

Ответ №1:

Pandas groupby кажется используемым инструментом, он может использовать столько группировок, сколько необходимо, и они могут быть типа list, series, column_name, index_level, callable… вы называете это

Например, вы можете сделать:

 df = df.groupby(
    [
        'Resolution', df.FrameRate//0.02 * 0.02,
        pd.cut(df.Runtime, bins=[45, 90, 95, 100, 120])
    ]
).File.apply(list)
  

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

Вы также можете получить полные строки для каждой группы, если по какой-либо причине с другими данными вы хотите разделить один df на множество и оставить его таким образом.

 for group_id, group_rows in df.groupby(...):
    # group id are tuples each with a unique combination of the grouping vectors
    # group_rows is a df of the matching rows, with the same columns as df
  

Комментарии:

1. где должно быть закрытие ] ? Я получаю invalid syntax сверху (без закрытия ] ).

2. Когда я набирал текст, все было в порядке, я внес правку, чтобы более четко показать структуру

3. отлично, спасибо за обновление. Всего пара вопросов по ответу: что такое .File — я никогда раньше этого не видел? И, во-вторых, зачем //0.02 *0.02 взламывать?

4. Ко всем столбцам фрейма данных можно обращаться как к атрибутам (если только имя столбца не является определенным методом для df как sum, mean и т.д.), возвращающим ряд. Разделение по этажам было просто примером использования модифицированных рядов в качестве группера без необходимости изменения исходного df.

5. о, я понимаю! Я думал, .File что это метод для фрейма данных, но я вижу, что это всего лишь поле, которое у меня есть… теперь это имеет гораздо больше смысла.