Cómo pivotar un marco de datos

358
  • ¿Qué es el pivote?
  • ¿Cómo giro?
  • ¿Es esto un pivote?
  • Formato largo a formato ancho?

He visto muchas preguntas sobre las tablas dinámicas. Incluso si no saben que están preguntando sobre tablas dinámicas, generalmente lo hacen. Es prácticamente imposible escribir una pregunta canónica y una respuesta que abarque todos los aspectos de pivotar ...

... Pero voy a intentarlo.


El problema con las preguntas y respuestas existentes es que, a menudo, la pregunta se centra en un matiz que el OP tiene problemas para generalizar con el fin de utilizar varias de las buenas respuestas existentes. Sin embargo, ninguna de las respuestas intenta dar una explicación completa (porque es una tarea desalentadora)

Mira algunos ejemplos de mi búsqueda de google

  1. ¿Cómo pivotar un marco de datos en Pandas?
    • Buena pregunta y respuesta. Pero la respuesta solo responde a la pregunta específica con poca explicación.
  2. tabla dinámica de pandas al marco de datos
    • En esta pregunta, el OP se ocupa de la salida del pivote. A saber, cómo se ven las columnas. OP quería que se pareciera a R. Esto no es muy útil para los usuarios de pandas.
  3. pandas que giran un marco de datos, filas duplicadas
    • Otra pregunta decente, pero la respuesta se centra en un método, a saber pd.DataFrame.pivot

Entonces, cuando alguien busca pivot, obtiene resultados esporádicos que probablemente no respondan a su pregunta específica.


Preparar

Es posible que note que nombré notablemente mis columnas y los valores de columna relevantes para que correspondan con la forma en que voy a pivotar en las respuestas a continuación.

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

Pregunta (s)

  1. ¿Por qué me sale ValueError: Index contains duplicate entries, cannot reshape

  2. ¿Cómo pivote de dftal manera que los colvalores sean columnas, los rowvalores sean el índice y la media de val0sean los valores?

    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. ¿Cómo pivote de dfmodo que los colvalores sean columnas, los rowvalores sean el índice, la media de val0sean los valores y los valores faltantes sean 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. ¿Puedo obtener algo más que mean, tal vez 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. ¿Puedo hacer más de una agregación a la vez?

           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. ¿Puedo agregar sobre varias columnas de valor?

          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. ¿Se puede subdividir por múltiples columnas?

    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. O

    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. ¿Puedo agregar la frecuencia en que la columna y las filas ocurren juntas, también conocido como "tabulación cruzada"?

    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. ¿Cómo convierto un DataFrame de largo a ancho girando SOLO en dos columnas? Dado,

    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

    Lo esperado debería ser algo así como

          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. ¿Cómo aplanar el índice múltiple a índice único después pivot

    Desde

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

    A

       1|1  2|1  2|2               
    a    2    1    1
    b    2    1    0
    c    1    0    0
piRSquared
fuente

Respuestas:

301

Comenzamos respondiendo la primera pregunta:

Pregunta 1

¿Por qué me sale ValueError: Index contains duplicate entries, cannot reshape

Esto ocurre porque pandas está intentando reindexar un objeto columnsu indexobjeto con entradas duplicadas. Hay varios métodos para usar que pueden realizar un pivote. Algunos de ellos no son adecuados para cuando hay duplicados de las teclas en las que se le pide que gire. Por ejemplo. Considere pd.DataFrame.pivot. Sé que hay entradas duplicadas que comparten los valores rowy col:

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

True

Entonces cuando pivotuso

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

Me sale el error mencionado anteriormente. De hecho, obtengo el mismo error cuando intento realizar la misma tarea con:

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

Aquí hay una lista de expresiones idiomáticas que podemos usar para pivotar

  1. pd.DataFrame.groupby + pd.DataFrame.unstack
    • Buen enfoque general para hacer casi cualquier tipo de pivote
    • Usted especifica todas las columnas que constituirán los niveles de fila pivotada y los niveles de columna en un grupo por. Sigue eso seleccionando las columnas restantes que desea agregar y las funciones que desea realizar la agregación. Finalmente, usted unstacklos niveles que desea estar en el índice de la columna.
  2. pd.DataFrame.pivot_table
    • Una versión glorificada de groupbyAPI más intuitiva. Para muchas personas, este es el enfoque preferido. Y es el enfoque previsto por los desarrolladores.
    • Especifique el nivel de fila, los niveles de columna, los valores que se agregarán y las funciones para realizar agregaciones.
  3. pd.DataFrame.set_index + pd.DataFrame.unstack
    • Conveniente e intuitivo para algunos (incluido yo mismo). No se pueden manejar claves agrupadas duplicadas.
    • Similar al groupbyparadigma, especificamos todas las columnas que eventualmente serán niveles de fila o columna y establecemos que sean el índice. Luego, unstacklos niveles que queremos en las columnas. Si los niveles de índice restantes o los niveles de columna no son únicos, este método fallará.
  4. pd.DataFrame.pivot
    • Muy similar a set_indexque comparte la limitación de clave duplicada. La API también es muy limitada. Sólo toma valores escalares para index, columns, values.
    • Similar al pivot_tablemétodo en el que seleccionamos filas, columnas y valores sobre los cuales pivotar. Sin embargo, no podemos agregar y si las filas o columnas no son únicas, este método fallará.
  5. pd.crosstab
    • Esta es una versión especializada pivot_tabley, en su forma más pura, es la forma más intuitiva de realizar varias tareas.
  6. pd.factorize + np.bincount
    • Esta es una técnica muy avanzada que es muy oscura pero muy rápida. No se puede usar en todas las circunstancias, pero cuando se puede usar y se siente cómodo usándolo, obtendrá las recompensas de rendimiento.
  7. pd.get_dummies + pd.DataFrame.dot
    • Lo uso para realizar inteligentemente la tabulación cruzada.

Ejemplos

Lo que voy a hacer para cada respuesta y pregunta subsiguiente es responderla usando pd.DataFrame.pivot_table. Luego proporcionaré alternativas para realizar la misma tarea.

Pregunta 3

¿Cómo pivote de dfmodo que los colvalores sean columnas, los rowvalores sean el índice, la media de val0sean los valores y los valores faltantes sean 0?

  • pd.DataFrame.pivot_table

    • fill_valueno está configurado por defecto. Tiendo a configurarlo adecuadamente. En este caso lo configuré en 0. Observe que omití la pregunta 2 ya que es lo mismo que esta respuesta sinfill_value
    • aggfunc='mean'es el valor predeterminado y no tuve que configurarlo. Lo incluí para ser explícito.

      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)

Pregunta 4

¿Puedo obtener algo más que mean, tal vez 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)

Pregunta 5

¿Puedo hacer más de una agregación a la vez?

Tenga en cuenta que para pivot_tabley crosstabnecesitaba pasar la lista de llamadas. Por otro lado, groupby.aggpuede tomar cadenas para un número limitado de funciones especiales. groupby.aggtambién habría tomado los mismos callables que pasamos a los demás, pero a menudo es más eficiente aprovechar los nombres de las funciones de cadena ya que se pueden obtener eficiencias.

  • 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')

Pregunta 6

¿Puedo agregar sobre varias columnas de valor?

  • pd.DataFrame.pivot_tablepasamos values=['val0', 'val1']pero podríamos haberlo dejado completamente

    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)

Pregunta 7

¿Se puede subdividir por múltiples columnas?

  • 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)

Pregunta 8

¿Se puede subdividir por múltiples columnas?

  • 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 porque el conjunto de claves es único tanto para las filas como para las columnas

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

Pregunta 9

¿Puedo agregar la frecuencia en que la columna y las filas ocurren juntas, también conocido como "tabulación cruzada"?

  • 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

Pregunta 10

¿Cómo convierto un DataFrame de largo a ancho girando SOLO en dos columnas?

El primer paso es asignar un número a cada fila; este número será el índice de fila de ese valor en el resultado pivote. Esto se hace usando 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

El segundo paso es usar la columna recién creada como índice para llamar 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

Pregunta 11

¿Cómo aplanar el índice múltiple a índice único después pivot

Si columnsescribe objectcon cadenajoin

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

más format

df.columns = df.columns.map('{0[0]}|{0[1]}'.format) 
piRSquared
fuente
43
¿Podría por favor considerar extender documentos oficiales ?
MaxU
¿Qué pasó con la respuesta a la pregunta 10? Consigo KeyError: 'A'. ¿Hay más en la respuesta?
Monica Heddneck
@MonicaHeddneck Lo revisaré nuevamente y lo actualizaré si es necesario. Sin embargo, 'A'se supone que hay una columna 'A'en su marco de datos para agrupar.
piRSquared
¿Puedo agregar sobre varias columnas de valor? La respuesta para esto funcionará para columnas de diferentes tipos de datos. por ejemplo: valores = ['val0', 'val1'], aquí val0 es int y val1 es cadena
Anil Kumar
1
no es necesario insertar la columna en la pregunta 10, se puede pasar directamente como argumento en la tabla dinámica
ansev
4

Para extender la respuesta de @ piRSquared otra versión de la Pregunta 10

Pregunta 10.1

Marco de datos:

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

Salida:

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

Usando df.groupbyypd.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

O una alternativa mucho mejor usando pd.pivot_tablecondf.squeeze.

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