Как я могу повернуть фрейм данных?

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

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

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


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

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

  1. Как повернуть фрейм данных в Pandas?
  • Хороший вопрос и ответ. Но ответ отвечает только на конкретный вопрос с небольшими пояснениями.
  1. сводная таблица pandas во фрейм данных
  • В этом вопросе OP связан с выходом опорной точки. А именно как выглядят колонки. OP хотел, чтобы он выглядел как R. Это не очень полезно для пользователей pandas.
  1. панды, поворачивающие фрейм данных, повторяющиеся строки
  • Еще один достойный вопрос, но ответ сосредоточен на одном методе, а именно 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
    
  11. Как мне сгладить множественный индекс до единственного индекса после pivot?

    Из

       1  2
       1  1  2
    a  2  1  1
    b  2  1  0
    c  1  0  0
    

    К

       1|1  2|1  2|2
    a    2    1    1
    b    2    1    0
    c    1    0    0
    
0
372
+500

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

Вопрос 1

Why do I get 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

How do I pivot df such that the col values are columns, row values are the index, mean of val0 are the values, and missing values are 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

Can I get something other than mean, like maybe 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

Can I do more that one aggregation at a time?

Обратите внимание, что для pivot_tableи crosstabмне нужно было передать список вызываемых. С другой стороны, 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

Can I aggregate over multiple value columns?

  • pd.DataFrame.pivot_tableмы проходим, 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

Can Subdivide by multiple columns?

  • 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

Can Subdivide by multiple columns?

  • 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

Can I aggregate the frequency in which the column and rows occur together, aka "cross tabulation"?

  • 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.crosstab

      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

How do I convert a DataFrame from long to wide by pivoting on ONLY two columns?

  • DataFrame.pivot

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

      df2.insert(0, 'count', df2.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(*df2)
      # df2.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
    
  • DataFrame.pivot_table

    Принимая DataFrame.pivotтолько столбцы, DataFrame.pivot_tableпринимает также и массивы, поэтому их GroupBy.cumcountможно передавать напрямую как indexбез создания явного столбца.

      df2.pivot_table(index=df2.groupby('A').cumcount(), columns='A', values='B')
    
      A         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
    

Вопрос 11

How do I flatten the multiple index to single index after pivot

Если columnsввести objectсо строкойjoin

df.columns = df.columns.map('|'.join)

еще format

df.columns = df.columns.map('{0[0]}|{0[1]}'.format)
8
  • 53
    Не могли бы вы рассмотреть вопрос о расширении официальных документов ? MaxU 15 дек.
  • что случилось с ответом на вопрос №10? Я понимаю KeyError: 'A'. Есть еще ответ? Monica Heddneck 27 сен '19 в 18:06
  • @MonicaHeddneck Я просмотрю его еще раз и при необходимости обновлю. Однако 'A'предполагается, что 'A'в вашем фрейме данных есть столбец для группировки. piRSquared 27 сен '19 в 20:19
  • 2
    нет необходимости вставлять столбец в вопросе 10, его можно передать напрямую в качестве аргумента в сводной таблицеansev 01 апр '20 в 18:03
  • 1
    @MonicaHeddneck Я считаю, что ссылки на dfдолжны быть изменены на df2. Если вы следили за мной, как и я, dfэто созданный ранее фрейм данных. CopOnTheRun 14 апр '20 в 6:16
13

Чтобы расширить ответ @ piRSquared на другую версию вопроса 10

Вопрос 10.1

DataFrame:

d = data = {'A': {0: 1, 1: 1, 2: 1, 3: 2, 4: 2, 5: 3, 6: 5},
 'B': {0: 'a', 1: 'b', 2: 'c', 3: 'a', 4: 'b', 5: 'a', 6: 'c'}}
df = pd.DataFrame(d)

   A  B
0  1  a
1  1  b
2  1  c
3  2  a
4  2  b
5  3  a
6  5  c

Выход:

   0     1     2
A
1  a     b     c
2  a     b  None
3  a  None  None
5  c  None  None

Использование df.groupbyиpd.Series.tolist

t = df.groupby('A')['B'].apply(list)
out = pd.DataFrame(t.tolist(),index=t.index)
out
   0     1     2
A
1  a     b     c
2  a     b  None
3  a  None  None
5  c  None  None

Или Гораздо лучшая альтернатива использования pd.pivot_tableсdf.squeeze.

t = df.pivot_table(index='A',values='B',aggfunc=list).squeeze()
out = pd.DataFrame(t.tolist(),index=t.index)
0
3

Чтобы лучше понять, как работает pivot, вы можете посмотреть пример из документации Pandas:

введите описание изображения здесь

df = pd.DataFrame({
    'foo': ['one', 'one', 'one', 'two', 'two', 'two'],
    'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
    'baz': [1, 2, 3, 4, 5, 6],
    'zoo': ['x', 'y', 'z', 'q', 'w', 't']
})

Таблица ввода:

   foo bar  baz zoo
0  one   A    1   x
1  one   B    2   y
2  one   C    3   z
3  two   A    4   q
4  two   B    5   w
5  two   C    6   t

Поворот :

pd.pivot(
    data=df,        
    index='foo',    # Column to use to make new frame’s index. If None, uses existing index.
    columns='bar',  # Column to use to make new frame’s columns.
    values='baz'    # Column(s) to use for populating new frame’s values.
)

Таблица вывода:

bar  A  B  C
foo         
one  1  2  3
two  4  5  6
1