Girar un dataframe de Pandas que contiene cadenas: error ‘No hay tipos numéricos para agregar’

Hay un buen número de preguntas sobre este error, pero después de mirar a mi alrededor todavía no puedo encontrar / envolver mi mente en torno a una solución todavía. Estoy tratando de girar un dataframe con cadenas, para que algunos datos de filas se conviertan en columnas, pero no estoy trabajando hasta ahora.

Forma de mi df

 Int64Index: 515932 entries, 0 to 515931 Data columns (total 5 columns): id 515932 non-null object cc_contact_id 515932 non-null object Network_Name 515932 non-null object question 515932 non-null object response_answer 515932 non-null object dtypes: object(5) memory usage: 23.6+ MB 

Formato de muestra

 id contact_id question response_answer 16 137519 2206 State Ca 17 137520 2206 State Ca 18 137521 2206 State Ca 19 137522 2206 State Ca 20 137523 2208 City Lancaster 21 137524 2208 City Lancaster 22 137525 2208 City Lancaster 23 137526 2208 City Lancaster 24 137527 2208 Trip_End Location Home 25 137528 2208 Trip_End Location Home 26 137529 2208 Trip_End Location Home 27 137530 2208 Trip_End Location Home 

A lo que me gustaría pivotar

 id contact_id State City Trip_End Location 16 137519 2206 Ca None None None 20 137523 2208 None Lancaster None None 24 137527 2208 None None None Home etc. etc. 

Donde los valores de las preguntas se convierten en columnas, con la respuesta en su columna correspondiente y conservando los identificadores

Lo que he intentado

 unified_df = pd.DataFrame(unified_data, columns=target_table_headers, dtype=object) pivot_table = unified_df.pivot_table('response_answer',['id','cc_contact_id'],'question') # OR pivot_table = unified_df.pivot_table('response_answer','question') 

DataError: No hay tipos numéricos para agregar

¿Cuál es la forma de pivotar un dataframe con valores de cadena?

El aggfunc predeterminado en pivot_table es np.sum y no sabe qué hacer con las cadenas y no ha indicado cuál debe ser el índice correctamente. Intentando algo como:

 pivot_table = unified_df.pivot_table(index=['id', 'contact_id'], columns='question', values='response_answer', aggfunc=lambda x: ' '.join(x)) 

Esto establece explícitamente una fila por id, contact_id par de id, contact_id y pivota el conjunto de valores de response_answer en question . El aggfunc solo asegura que si tiene varias respuestas a la misma pregunta en los datos sin procesar, solo las concatenaremos con espacios. La syntax de pivot_table puede variar dependiendo de su versión de pandas.

Aquí hay un ejemplo rápido:

 In [24]: import pandas as pd In [25]: import random In [26]: df = pd.DataFrame({'id':[100*random.randint(10, 50) for _ in range(100)], 'question': [str(random.randint(0,3)) for _ in range(100)], 'response': [str(random.randint(100,120)) for _ in range(100)]}) In [27]: df.head() Out[27]: id question response 0 3100 1 116 1 4500 2 113 2 5000 1 120 3 3900 2 103 4 4300 0 117 In [28]: df.info()  Int64Index: 100 entries, 0 to 99 Data columns (total 3 columns): id 100 non-null int64 question 100 non-null object response 100 non-null object dtypes: int64(1), object(2) memory usage: 3.1+ KB In [29]: df.pivot_table(index='id', columns='question', values='response', aggfunc=lambda x: ' '.join(x)).head() Out[29]: question 0 1 2 3 id 1000 110 120 NaN 100 NaN 1100 NaN 106 108 104 NaN 1200 104 113 119 NaN 101 1300 102 NaN 116 108 120 1400 NaN NaN 116 NaN 

Hay varias maneras.

1

 df1 = df.groupby(["id","contact_id","Network_Name","question"])['response_answer'].aggregate(lambda x: x).unstack().reset_index() df1.columns=df1.columns.tolist() print (df1) 

2

 df1 = df.set_index(["id","contact_id","Network_Name","question"])['response_answer'].unstack().reset_index() df1.columns=df1.columns.tolist() print (df1) 

3

 df1 = df.groupby(["id","contact_id","Network_Name","question"])['response_answer'].aggregate('first').unstack().reset_index() df1.columns=df1.columns.tolist() print (df1) 

4

 df1 = df.pivot_table(index=["id","contact_id","Network_Name"], columns='question', values=['response_answer'], aggfunc='first') df1.columns = df1.columns.droplevel() df1 = df1.reset_index() df1.columns=df1.columns.tolist() print (df1) 

Mismos ans.

  id contact_id Network_Name City State Trip_End_Location 0 16 137519 2206 None Ca None 1 17 137520 2206 None Ca None 2 18 137521 2206 None Ca None 3 19 137522 2206 None Ca None 4 20 137523 2208 Lancaster None None 5 21 137524 2208 Lancaster None None 6 22 137525 2208 Lancaster None None 7 23 137526 2208 Lancaster None None 8 24 137527 2208 None None Home 9 25 137528 2208 None None Home 10 26 137529 2208 None None Home 11 27 137530 2208 None None Home