¿Cómo dividir la columna de tuplas en el dataframe pandas?

Tengo un dataframe de pandas (esto es solo una pequeña parte)

>>> d1 y norm test y norm train len(y_train) len(y_test) \ 0 64.904368 116.151232 1645 549 1 70.852681 112.639876 1645 549 SVR RBF \ 0 (35.652207342877873, 22.95533537448393) 1 (39.563683797747622, 27.382483096332511) LCV \ 0 (19.365430594452338, 13.880062435173587) 1 (19.099614489458364, 14.018867136617146) RIDGE CV \ 0 (4.2907610988480362, 12.416745648065584) 1 (4.18864306788194, 12.980833914392477) RF \ 0 (9.9484841581029428, 16.46902345373697) 1 (10.139848213735391, 16.282141345406522) GB \ 0 (0.012816232716538605, 15.950164822266007) 1 (0.012814519804493328, 15.305745202851712) ET DATA 0 (0.00034337162272515505, 16.284800366214057) j2m 1 (0.00024811554516431878, 15.556506191784194) j2m >>> 

Quiero dividir todas las columnas que contienen tuplas. Por ejemplo, quiero reemplazar la columna LCV con las columnas LCV-a y LCV-b .

¿Cómo puedo hacer eso?

Puedes hacer esto haciendo pd.DataFrame(col.tolist()) en esa columna:

 In [2]: df = pd.DataFrame({'a':[1,2], 'b':[(1,2), (3,4)]}) In [3]: df Out[3]: ab 0 1 (1, 2) 1 2 (3, 4) In [4]: df['b'].tolist() Out[4]: [(1, 2), (3, 4)] In [5]: pd.DataFrame(df['b'].tolist(), index=df.index) Out[5]: 0 1 0 1 2 1 3 4 In [6]: df[['b1', 'b2']] = pd.DataFrame(df['b'].tolist(), index=df.index) In [7]: df Out[7]: ab b1 b2 0 1 (1, 2) 1 2 1 2 (3, 4) 3 4 

Nota: en una versión anterior, esta respuesta recomienda utilizar df['b'].apply(pd.Series) lugar de pd.DataFrame(df['b'].tolist(), index=df.index) . Eso también funciona (porque hace de cada tupla una Serie, que luego se ve como una fila de un dataframe), pero es más lento / usa más memoria que la versión de la tolist , como lo señalan las otras respuestas aquí (gracias a @denfromufa ).
Actualicé esta respuesta para asegurarme de que la respuesta más visible tenga la mejor solución.

En conjuntos de datos mucho más grandes, encontré que .apply() es algunos órdenes más lento que pd.DataFrame(df['b'].values.tolist(), index=df.index)

Este problema de rendimiento se cerró en GitHub, aunque no estoy de acuerdo con esta decisión:

https://github.com/pandas-dev/pandas/issues/11615

EDIT: basado en esta respuesta: https://stackoverflow.com/a/44196843/2230844

Sé que esto es de hace un tiempo, pero una advertencia de la segunda solución:

 pd.DataFrame(df['b'].values.tolist()) 

es que descartará explícitamente el índice y agregará un índice secuencial predeterminado, mientras que la respuesta aceptada

 apply(pd.Series) 

no lo hará, ya que el resultado de aplicar retendrá el índice de fila. Mientras que el orden se retiene inicialmente de la matriz original, los pandas intentarán coincidir con las indicaciones de los dos marcos de datos.

Esto puede ser muy importante si está tratando de establecer las filas en una matriz indexada numéricamente, y los pandas intentarán automáticamente hacer coincidir el índice de la nueva matriz con la antigua, y causar cierta distorsión en el orden.

Una mejor solución híbrida sería establecer el índice del dataframe original en el nuevo, es decir,

 pd.DataFrame(df['b'].values.tolist(), index=df.index) 

Lo que mantendrá la velocidad de usar el segundo método al tiempo que garantiza que el orden y la indexación se conserven en el resultado.

Creo que una forma más sencilla es:

 >>> import pandas as pd >>> df = pd.DataFrame({'a':[1,2], 'b':[(1,2), (3,4)]}) >>> df ab 0 1 (1, 2) 1 2 (3, 4) >>> df['b_a']=df['b'].str[0] >>> df['b_b']=df['b'].str[1] >>> df ab b_a b_b 0 1 (1, 2) 1 2 1 2 (3, 4) 3 4