Как повернуть рамку данных

  • Что такое пивот?
  • Как мне повернуть?
  • Это стержень?
  • Длинный формат для широкого формата?

Я видел много вопросов о сводных таблицах. Даже если они не знают, что спрашивают о сводных таблицах, они обычно так и делают. Практически невозможно написать канонический вопрос и ответ, который охватывает все аспекты поворота....

... Но я собираюсь попробовать.


Проблема с существующими вопросами и ответами состоит в том, что часто вопрос фокусируется на нюансе, который ОП затрудняет обобщение, чтобы использовать ряд существующих хороших ответов. Тем не менее, ни один из ответов не пытается дать исчерпывающее объяснение (потому что это сложная задача)

Посмотрите несколько примеров из моего поиска Google

  1. Как развернуть датафрейм в Pandas?
    • Хороший вопрос и ответ. Но ответ только отвечает на конкретный вопрос с небольшим объяснением.
  2. сводная таблица панд к фрейму данных
    • В этом вопросе OP касается вывода разворота. А именно, как выглядят колонны. ОП хотел, чтобы это выглядело как R. Это не очень полезно для пользователей панд.
  3. Панды, поворачивающие фрейм данных, повторяющиеся строки
    • Еще один достойный вопрос, но ответ сосредоточен на одном методе, а именно pd.DataFrame.pivot

Поэтому всякий раз, когда кто-то ищет pivot он получает спорадические результаты, которые, вероятно, не будут отвечать на их конкретный вопрос.


Настроить

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

import numpy as np
import pandas as pd
from numpy.core.defchararray import add

np.random.seed([3,1415])
n = 20

cols = np.array(['key', 'row', 'item', 'col'])
arr1 = (np.random.randint(5, size=(n, 4)) // [2, 1, 2, 1]).astype(str)

df = pd.DataFrame(
    add(cols, arr1), columns=cols
).join(
    pd.DataFrame(np.random.rand(n, 2).round(2)).add_prefix('val')
)
print(df)

     key   row   item   col  val0  val1
0   key0  row3  item1  col3  0.81  0.04
1   key1  row2  item1  col2  0.44  0.07
2   key1  row0  item1  col0  0.77  0.01
3   key0  row4  item0  col2  0.15  0.59
4   key1  row0  item2  col1  0.81  0.64
5   key1  row2  item2  col4  0.13  0.88
6   key2  row4  item1  col3  0.88  0.39
7   key1  row4  item1  col1  0.10  0.07
8   key1  row0  item2  col4  0.65  0.02
9   key1  row2  item0  col2  0.35  0.61
10  key2  row0  item2  col1  0.40  0.85
11  key2  row4  item1  col2  0.64  0.25
12  key0  row2  item2  col3  0.50  0.44
13  key0  row4  item1  col4  0.24  0.46
14  key1  row3  item2  col3  0.28  0.11
15  key0  row3  item1  col1  0.31  0.23
16  key0  row0  item2  col3  0.86  0.01
17  key0  row4  item0  col3  0.64  0.21
18  key2  row2  item2  col0  0.13  0.45
19  key0  row2  item0  col4  0.37  0.70

Вопросы)

  1. Почему я получаю ValueError: Index contains duplicate entries, cannot reshape

  2. Как мне повернуть df, чтобы значения col были столбцами, значения row были индексом, а средние значения val0 были значениями?

    col   col0   col1   col2   col3  col4
    row                                  
    row0  0.77  0.605    NaN  0.860  0.65
    row2  0.13    NaN  0.395  0.500  0.25
    row3   NaN  0.310    NaN  0.545   NaN
    row4   NaN  0.100  0.395  0.760  0.24
    
  3. Как мне повернуть df, чтобы значения col были столбцами, значения row были индексом, средние значения val0 были значениями, а отсутствующие значения равны 0?

    col   col0   col1   col2   col3  col4
    row                                  
    row0  0.77  0.605  0.000  0.860  0.65
    row2  0.13  0.000  0.395  0.500  0.25
    row3  0.00  0.310  0.000  0.545  0.00
    row4  0.00  0.100  0.395  0.760  0.24
    
  4. Могу ли я получить что-то кроме mean, например, sum?

    col   col0  col1  col2  col3  col4
    row                               
    row0  0.77  1.21  0.00  0.86  0.65
    row2  0.13  0.00  0.79  0.50  0.50
    row3  0.00  0.31  0.00  1.09  0.00
    row4  0.00  0.10  0.79  1.52  0.24
    
  5. Могу ли я сделать больше одной агрегации за раз?

           sum                          mean                           
    col   col0  col1  col2  col3  col4  col0   col1   col2   col3  col4
    row                                                                
    row0  0.77  1.21  0.00  0.86  0.65  0.77  0.605  0.000  0.860  0.65
    row2  0.13  0.00  0.79  0.50  0.50  0.13  0.000  0.395  0.500  0.25
    row3  0.00  0.31  0.00  1.09  0.00  0.00  0.310  0.000  0.545  0.00
    row4  0.00  0.10  0.79  1.52  0.24  0.00  0.100  0.395  0.760  0.24
    
  6. Могу ли я объединить несколько столбцов значений?

          val0                             val1                          
    col   col0   col1   col2   col3  col4  col0   col1  col2   col3  col4
    row                                                                  
    row0  0.77  0.605  0.000  0.860  0.65  0.01  0.745  0.00  0.010  0.02
    row2  0.13  0.000  0.395  0.500  0.25  0.45  0.000  0.34  0.440  0.79
    row3  0.00  0.310  0.000  0.545  0.00  0.00  0.230  0.00  0.075  0.00
    row4  0.00  0.100  0.395  0.760  0.24  0.00  0.070  0.42  0.300  0.46
    
  7. Можно разделить на несколько столбцов?

    item item0             item1                         item2                   
    col   col2  col3  col4  col0  col1  col2  col3  col4  col0   col1  col3  col4
    row                                                                          
    row0  0.00  0.00  0.00  0.77  0.00  0.00  0.00  0.00  0.00  0.605  0.86  0.65
    row2  0.35  0.00  0.37  0.00  0.00  0.44  0.00  0.00  0.13  0.000  0.50  0.13
    row3  0.00  0.00  0.00  0.00  0.31  0.00  0.81  0.00  0.00  0.000  0.28  0.00
    row4  0.15  0.64  0.00  0.00  0.10  0.64  0.88  0.24  0.00  0.000  0.00  0.00
    
  8. Или же

    item      item0             item1                         item2                  
    col        col2  col3  col4  col0  col1  col2  col3  col4  col0  col1  col3  col4
    key  row                                                                         
    key0 row0  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.86  0.00
         row2  0.00  0.00  0.37  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.50  0.00
         row3  0.00  0.00  0.00  0.00  0.31  0.00  0.81  0.00  0.00  0.00  0.00  0.00
         row4  0.15  0.64  0.00  0.00  0.00  0.00  0.00  0.24  0.00  0.00  0.00  0.00
    key1 row0  0.00  0.00  0.00  0.77  0.00  0.00  0.00  0.00  0.00  0.81  0.00  0.65
         row2  0.35  0.00  0.00  0.00  0.00  0.44  0.00  0.00  0.00  0.00  0.00  0.13
         row3  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.28  0.00
         row4  0.00  0.00  0.00  0.00  0.10  0.00  0.00  0.00  0.00  0.00  0.00  0.00
    key2 row0  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.40  0.00  0.00
         row2  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.13  0.00  0.00  0.00
         row4  0.00  0.00  0.00  0.00  0.00  0.64  0.88  0.00  0.00  0.00  0.00  0.00
    
  9. Могу ли я объединить частоту, с которой столбец и строки встречаются вместе, то есть "кросс-табуляция"?

    col   col0  col1  col2  col3  col4
    row                               
    row0     1     2     0     1     1
    row2     1     0     2     1     2
    row3     0     1     0     2     0
    row4     0     1     2     2     1
    
  10. Как преобразовать DataFrame из длинного в широкий, поворачивая ТОЛЬКО на два столбца? Дано,

    np.random.seed([3, 1415])
    df2 = pd.DataFrame({'A': list('aaaabbbc'), 'B': np.random.choice(15, 8)})        
    df2        
       A   B
    0  a   0
    1  a  11
    2  a   2
    3  a  11
    4  b  10
    5  b  10
    6  b  14
    7  c   7
    

    Ожидаемый должен выглядеть примерно так

          a     b    c
    0   0.0  10.0  7.0
    1  11.0  10.0  NaN
    2   2.0  14.0  NaN
    3  11.0   NaN  NaN
    

Ответы

Ответ 1

Начнем с ответа на первый вопрос:

Вопрос 1

Почему я получаю ValueError: Index contains duplicate entries, cannot reshape

Это происходит потому, что pandas пытается переиндексировать columns или index объект с повторяющимися записями. Существуют различные методы, которые могут использовать для разворота. Некоторые из них не очень подходят, когда есть дубликаты клавиш, в которых его просят повернуть. Например. Рассмотрим pd.DataFrame.pivot. Я знаю, что есть повторяющиеся записи, которые разделяют значения row и col:

df.duplicated(['row', 'col']).any()

True

Поэтому, когда я pivot с помощью

df.pivot(index='row', columns='col', values='val0')

Я получаю ошибку, упомянутую выше. Фактически, я получаю ту же ошибку, когда пытаюсь выполнить ту же задачу с:

df.set_index(['row', 'col'])['val0'].unstack()

Вот список идиом, которые мы можем использовать для поворота

  1. pd.DataFrame.groupby + pd.DataFrame.unstack
    • Хороший общий подход для выполнения практически любого типа разворота
    • Вы указываете все столбцы, которые будут составлять поворотные уровни строк и уровни столбцов в одной группе. Вы следуете за этим, выбирая оставшиеся столбцы, которые вы хотите агрегировать, и функции, которые вы хотите выполнить агрегацию. Наконец, вы unstack уровни, которые вы хотите видеть в индексе столбца.
  2. pd.DataFrame.pivot_table
    • Прославленная версия groupby с более интуитивным API. Для многих это предпочтительный подход. И это намеченный подход со стороны разработчиков.
    • Укажите уровень строки, уровни столбцов, значения для агрегирования и функции для выполнения агрегации.
  3. pd.DataFrame.set_index + pd.DataFrame.unstack
    • Удобный и интуитивно понятный для некоторых (включая меня). Не удается обработать дублированные сгруппированные ключи.
    • Подобно парадигме groupby, мы указываем все столбцы, которые в конечном итоге будут уровнями строк или столбцов, и устанавливаем их в качестве индекса. Затем мы unstack уровни, которые мы хотим в столбцах. Если оставшиеся уровни индекса или уровни столбца не являются уникальными, этот метод завершится ошибкой.
  4. pd.DataFrame.pivot
    • Очень похоже на set_index в том, что оно разделяет ограничение дубликата ключа. API также очень ограничен. Он принимает только скалярные значения для index, columns, values.
    • Подобно методу pivot_table, мы выбираем строки, столбцы и значения для поворота. Однако мы не можем агрегировать, и если строки или столбцы не являются уникальными, этот метод завершится ошибкой.
  5. pd.crosstab
    • Это специализированная версия pivot_table и в ее чистом виде это наиболее интуитивно понятный способ выполнения нескольких задач.
  6. pd.factorize + np.bincount
    • Это очень продвинутая техника, которая очень непонятна, но очень быстра. Его нельзя использовать при любых обстоятельствах, но когда его можно использовать, и вы можете его использовать, вы получите плоды производительности.
  7. pd.get_dummies + pd.DataFrame.dot
    • Я использую это для умного выполнения кросс-табуляции.

Примеры

Что я собираюсь сделать для каждого последующего ответа и вопроса, так это ответить на него с помощью pd.DataFrame.pivot_table. Затем я предоставлю альтернативы для выполнения той же задачи.

Вопрос 3

Как мне повернуть df, чтобы значения col были столбцами, значения row были индексом, средние значения val0 были значениями, а отсутствующие значения равны 0?

  • pd.DataFrame.pivot_table

    • fill_value не устанавливается по умолчанию. Я склонен устанавливать это соответствующим образом. В этом случае я установил его на 0. Заметьте, что я пропустил вопрос 2, так как он совпадает с ответом без fill_value
    • aggfunc='mean' - это значение по умолчанию, и мне не нужно было его устанавливать. Я включил это, чтобы быть явным.

      df.pivot_table(
          values='val0', index='row', columns='col',
          fill_value=0, aggfunc='mean')
      
      col   col0   col1   col2   col3  col4
      row                                  
      row0  0.77  0.605  0.000  0.860  0.65
      row2  0.13  0.000  0.395  0.500  0.25
      row3  0.00  0.310  0.000  0.545  0.00
      row4  0.00  0.100  0.395  0.760  0.24
      
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].mean().unstack(fill_value=0)
    
  • pd.crosstab

    pd.crosstab(
        index=df['row'], columns=df['col'],
        values=df['val0'], aggfunc='mean').fillna(0)
    

Вопрос 4

Могу ли я получить что-то кроме mean, например, sum?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        values='val0', index='row', columns='col',
        fill_value=0, aggfunc='sum')
    
    col   col0  col1  col2  col3  col4
    row                               
    row0  0.77  1.21  0.00  0.86  0.65
    row2  0.13  0.00  0.79  0.50  0.50
    row3  0.00  0.31  0.00  1.09  0.00
    row4  0.00  0.10  0.79  1.52  0.24
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].sum().unstack(fill_value=0)
    
  • pd.crosstab

    pd.crosstab(
        index=df['row'], columns=df['col'],
        values=df['val0'], aggfunc='sum').fillna(0)
    

Вопрос 5

Могу ли я сделать больше одной агрегации за раз?

Обратите внимание, что для pivot_table и cross_tab мне нужно было передать список вызываемых объектов. С другой стороны, groupby.agg может принимать строки для ограниченного числа специальных функций. groupby.agg также взял бы те же самые вызовы, которые мы передали другим, но зачастую эффективнее использовать имена строковых функций, поскольку есть преимущества, которые нужно получить.

  • pd.DataFrame.pivot_table

    df.pivot_table(
        values='val0', index='row', columns='col',
        fill_value=0, aggfunc=[np.size, np.mean])
    
         size                      mean                           
    col  col0 col1 col2 col3 col4  col0   col1   col2   col3  col4
    row                                                           
    row0    1    2    0    1    1  0.77  0.605  0.000  0.860  0.65
    row2    1    0    2    1    2  0.13  0.000  0.395  0.500  0.25
    row3    0    1    0    2    0  0.00  0.310  0.000  0.545  0.00
    row4    0    1    2    2    1  0.00  0.100  0.395  0.760  0.24
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].agg(['size', 'mean']).unstack(fill_value=0)
    
  • pd.crosstab

    pd.crosstab(
        index=df['row'], columns=df['col'],
        values=df['val0'], aggfunc=[np.size, np.mean]).fillna(0, downcast='infer')
    

Вопрос 6

Могу ли я объединить несколько столбцов значений?

  • pd.DataFrame.pivot_table мы передаем values=['val0', 'val1'] но мы могли бы полностью values=['val0', 'val1']

    df.pivot_table(
        values=['val0', 'val1'], index='row', columns='col',
        fill_value=0, aggfunc='mean')
    
          val0                             val1                          
    col   col0   col1   col2   col3  col4  col0   col1  col2   col3  col4
    row                                                                  
    row0  0.77  0.605  0.000  0.860  0.65  0.01  0.745  0.00  0.010  0.02
    row2  0.13  0.000  0.395  0.500  0.25  0.45  0.000  0.34  0.440  0.79
    row3  0.00  0.310  0.000  0.545  0.00  0.00  0.230  0.00  0.075  0.00
    row4  0.00  0.100  0.395  0.760  0.24  0.00  0.070  0.42  0.300  0.46
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0', 'val1'].mean().unstack(fill_value=0)
    

Вопрос 7

Можно разделить на несколько столбцов?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        values='val0', index='row', columns=['item', 'col'],
        fill_value=0, aggfunc='mean')
    
    item item0             item1                         item2                   
    col   col2  col3  col4  col0  col1  col2  col3  col4  col0   col1  col3  col4
    row                                                                          
    row0  0.00  0.00  0.00  0.77  0.00  0.00  0.00  0.00  0.00  0.605  0.86  0.65
    row2  0.35  0.00  0.37  0.00  0.00  0.44  0.00  0.00  0.13  0.000  0.50  0.13
    row3  0.00  0.00  0.00  0.00  0.31  0.00  0.81  0.00  0.00  0.000  0.28  0.00
    row4  0.15  0.64  0.00  0.00  0.10  0.64  0.88  0.24  0.00  0.000  0.00  0.00
    
  • pd.DataFrame.groupby

    df.groupby(
        ['row', 'item', 'col']
    )['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
    

Вопрос 8

Можно разделить на несколько столбцов?

  • pd.DataFrame.pivot_table

    df.pivot_table(
        values='val0', index=['key', 'row'], columns=['item', 'col'],
        fill_value=0, aggfunc='mean')
    
    item      item0             item1                         item2                  
    col        col2  col3  col4  col0  col1  col2  col3  col4  col0  col1  col3  col4
    key  row                                                                         
    key0 row0  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.86  0.00
         row2  0.00  0.00  0.37  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.50  0.00
         row3  0.00  0.00  0.00  0.00  0.31  0.00  0.81  0.00  0.00  0.00  0.00  0.00
         row4  0.15  0.64  0.00  0.00  0.00  0.00  0.00  0.24  0.00  0.00  0.00  0.00
    key1 row0  0.00  0.00  0.00  0.77  0.00  0.00  0.00  0.00  0.00  0.81  0.00  0.65
         row2  0.35  0.00  0.00  0.00  0.00  0.44  0.00  0.00  0.00  0.00  0.00  0.13
         row3  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.28  0.00
         row4  0.00  0.00  0.00  0.00  0.10  0.00  0.00  0.00  0.00  0.00  0.00  0.00
    key2 row0  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.40  0.00  0.00
         row2  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.13  0.00  0.00  0.00
         row4  0.00  0.00  0.00  0.00  0.00  0.64  0.88  0.00  0.00  0.00  0.00  0.00
    
  • pd.DataFrame.groupby

    df.groupby(
        ['key', 'row', 'item', 'col']
    )['val0'].mean().unstack(['item', 'col']).fillna(0).sort_index(1)
    
  • pd.DataFrame.set_index потому что набор ключей уникален как для строк, так и для столбцов.

    df.set_index(
        ['key', 'row', 'item', 'col']
    )['val0'].unstack(['item', 'col']).fillna(0).sort_index(1)
    

Вопрос 9

Могу ли я объединить частоту, с которой столбец и строки встречаются вместе, то есть "кросс-табуляция"?

  • pd.DataFrame.pivot_table

    df.pivot_table(index='row', columns='col', fill_value=0, aggfunc='size')
    
        col   col0  col1  col2  col3  col4
    row                               
    row0     1     2     0     1     1
    row2     1     0     2     1     2
    row3     0     1     0     2     0
    row4     0     1     2     2     1
    
  • pd.DataFrame.groupby

    df.groupby(['row', 'col'])['val0'].size().unstack(fill_value=0)
    
  • pd.cross_tab

    pd.crosstab(df['row'], df['col'])
    
  • pd.factorize + np.bincount

    # get integer factorization 'i' and unique values 'r'
    # for column ''row''
    i, r = pd.factorize(df['row'].values)
    # get integer factorization 'j' and unique values 'c'
    # for column ''col''
    j, c = pd.factorize(df['col'].values)
    # 'n' will be the number of rows
    # 'm' will be the number of columns
    n, m = r.size, c.size
    # 'i * m + j' is a clever way of counting the 
    # factorization bins assuming a flat array of length
    # 'n * m'.  Which is why we subsequently reshape as '(n, m)'
    b = np.bincount(i * m + j, minlength=n * m).reshape(n, m)
    # BTW, whenever I read this, I think 'Bean, Rice, and Cheese'
    pd.DataFrame(b, r, c)
    
          col3  col2  col0  col1  col4
    row3     2     0     0     1     0
    row2     1     2     1     0     2
    row0     1     0     1     2     1
    row4     2     2     0     1     1
    
  • pd.get_dummies

    pd.get_dummies(df['row']).T.dot(pd.get_dummies(df['col']))
    
          col0  col1  col2  col3  col4
    row0     1     2     0     1     1
    row2     1     0     2     1     2
    row3     0     1     0     2     0
    row4     0     1     2     2     1
    

Вопрос 10

Как преобразовать DataFrame из длинного в широкий, поворачивая ТОЛЬКО на два столбца?

Первым шагом является присвоение номера каждой строке - этот номер будет индексом строки этого значения в сводном результате. Это делается с помощью GroupBy.cumcount:

df2.insert(0, 'count', df.groupby('A').cumcount())
df2

   count  A   B
0      0  a   0
1      1  a  11
2      2  a   2
3      3  a  11
4      0  b  10
5      1  b  10
6      2  b  14
7      0  c   7

Второй шаг - использовать вновь созданный столбец в качестве индекса для вызова DataFrame.pivot.

df2.pivot(*df)
# df.pivot(index='count', columns='A', values='B')

A         a     b    c
count                 
0       0.0  10.0  7.0
1      11.0  10.0  NaN
2       2.0  14.0  NaN
3      11.0   NaN  NaN

Чтобы сделать это в одной строке, используйте assign:

df2.assign(count=df.groupby('A').cumcount()).pivot('count', 'A', 'B')

A         a     b    c
count                 
0      12.0  11.0  9.0
1       5.0   3.0  NaN
2       0.0   7.0  NaN
3       3.0   NaN  NaN

Ответ 2

Сообщение piRSquared является очень полным и охватывает большинство стандартных случаев использования. Вот еще одна вещь, которую я вижу, часто всплывают, и я думаю, что она заслуживает внимания.

Вопрос

Это общее требование для поворота DataFrame только с двумя столбцами. Обычно один из столбцов (содержащий дубликаты) будет служить столбцом в сводном результате. Проблема в том, что нет 3-го столбца, который мог бы служить индексом.

Вот пример для иллюстрации.

np.random.seed(0)
df = pd.DataFrame({'A': list('aaaabbbc'), 'B': np.random.choice(15, 8)})

df

   A   B
0  a  12
1  a   5
2  a   0
3  a   3
4  b  11
5  b   3
6  b   7
7  c   9

Ожидаемый должен выглядеть примерно так

    a   b  c
0  12  11  9
1   5   3  0
2   0   7  0
3   3   0  0

Решение

Первым шагом является присвоение номера каждой строке - этот номер будет индексом строки этого значения в сводном результате. Это делается с помощью GroupBy.cumcount:

df.insert(0, 'count', df.groupby('A').cumcount())
df

   count  A   B
0      0  a  12
1      1  a   5
2      2  a   0
3      3  a   3
4      0  b  11
5      1  b   3
6      2  b   7
7      0  c   9

Второй шаг - использовать вновь созданный столбец в качестве индекса для вызова DataFrame.pivot.

df.pivot(*df)
# df.pivot(index='count', columns='A', values='B')

A         a     b    c
count                 
0      12.0  11.0  9.0
1       5.0   3.0  NaN
2       0.0   7.0  NaN
3       3.0   NaN  NaN

Чтобы сделать это в одной строке, используйте assign:

df.assign(count=df.groupby('A').cumcount()).pivot('count', 'A', 'B')

A         a     b    c
count                 
0      12.0  11.0  9.0
1       5.0   3.0  NaN
2       0.0   7.0  NaN
3       3.0   NaN  NaN

Резюме: когда я использую что?

Этот QnA представил много концепций и функций. Вот мои эмпирические правила при определении того, какая функция лучше всего подходит для каких вариантов использования.

  • pivot - только структура/изменение формы (без агрегации)
  • pivot_table - изменение формы с агрегацией
  • GroupBy + unstack - аналогично pivot_table, изменение формы с агрегацией (может быть медленнее, проверьте это на ваших данных)
  • crosstab pivot_table - аналогична pivot_table, но оптимизирована для кросс- pivot_table счетчиков между двумя наборами столбцов.