Pandas DataFrame: marco de transformación utilizando valores únicos de una columna

Tengo un dataframe pandas / csv del formulario

date Country Type Val 2013-01-01 USA x 23 2013-01-01 USA y 13 2013-01-01 MX x 11 2013-01-01 MX y 14 2013-01-02 USA x 20 2013-01-02 USA y 19 2013-01-02 MX x 14 2013-01-02 MX y 16 

Quiero convertir esto a un formulario

 date Country xy 2013-01-01 USA 23 13 2013-01-01 MX 11 14 2013-01-02 USA 20 19 2013-01-02 MX 14 16 

En general, estoy buscando una manera de transformar una tabla usando valores únicos de una sola columna.

He mirado a pivot y groupby pero no groupby la forma exacta.

SUGERENCIA: posiblemente esto pueda solucionarse mediante pivot pero no he podido obtener el formulario

Probablemente no sea la forma más elegante posible, pero usando el desastackmiento :

 >>> df date Country Type Val 0 2013-01-01 USA x 23 1 2013-01-01 USA y 13 2 2013-01-01 MX x 11 3 2013-01-01 MX y 14 4 2013-01-02 USA x 20 5 2013-01-02 USA y 19 6 2013-01-02 MX x 14 7 2013-01-02 MX y 16 >>> df.set_index(['date', 'Country', 'Type']).unstack('Type').reset_index() date Country Val Type xy 0 2013-01-01 MX 11 14 1 2013-01-01 USA 23 13 2 2013-01-02 MX 14 16 3 2013-01-02 USA 20 19 

Un poco más en general, y eliminando las extrañas columnas jerárquicas en el resultado:

 >>> cols = [c for c in df.columns if c not in {'Type', 'Val'}] >>> df2 = df.set_index(cols + ['Type']).unstack('Type') >>> df2 Val Type xy date Country 2013-01-01 MX 11 14 USA 23 13 2013-01-02 MX 14 16 USA 20 19 >>> df2.columns = df2.columns.levels[1] >>> df2.columns.name = None >>> df2 xy date Country 2013-01-01 MX 11 14 USA 23 13 2013-01-02 MX 14 16 USA 20 19 >>> df2.reset_index() date Country xy 0 2013-01-01 MX 11 14 1 2013-01-01 USA 23 13 2 2013-01-02 MX 14 16 3 2013-01-02 USA 20 19 

Preparé mi propia solución basada en pivotes para el mismo problema antes de encontrar la respuesta de Dougal, pensé que lo publicaría para la posteridad ya que me parece más legible:

 >>> pd.__version__ '0.15.0' >>> df date Country Type Val 0 2013-01-01 USA x 23 1 2013-01-01 USA y 13 2 2013-01-01 MX x 11 3 2013-01-01 MX y 14 4 2013-01-02 USA x 20 5 2013-01-02 USA y 19 6 2013-01-02 MX x 14 7 2013-01-02 MX y 16 >>> pt=df.pivot_table(values='Val', ... columns='Type', ... index=['date','Country'], ... ) >>> pt Type xy date Country 2013-01-01 MX 11 14 USA 23 13 2013-01-02 MX 14 16 USA 20 19 

Y luego continuar con las limpiezas de Dougal:

 >>> pt.columns.name=None >>> pt.reset_index() date Country xy 0 2013-01-01 MX 11 14 1 2013-01-01 USA 23 13 2 2013-01-02 MX 14 16 3 2013-01-02 USA 20 19 

Tenga en cuenta que DataFrame.to_csv() produce su salida solicitada:

 >>> print(pt.to_csv()) date,Country,x,y 2013-01-01,MX,11,14 2013-01-01,USA,23,13 2013-01-02,MX,14,16 2013-01-02,USA,20,19 

Guardemos su dataframe original en df Entonces al menos en la versión 0.18.1 puede hacer:

 df.pivot_table(values="Val", index=['date', 'Country'], columns='Type') 

da la respuesta correcta:

 Type xy date Country 2013-01-01 MX 11 14 USA 23 13 2013-01-02 MX 14 16 USA 20 19