¿Cómo fusionar / combinar columnas en pandas?

Tengo un dataframe (ejemplo) con 4 columnas:

data = {'A': ['a', 'b', 'c', 'd', 'e', 'f'], 'B': [42, 52, np.nan, np.nan, np.nan, np.nan], 'C': [np.nan, np.nan, 31, 2, np.nan, np.nan], 'D': [np.nan, np.nan, np.nan, np.nan, 62, 70]} df = pd.DataFrame(data, columns = ['A', 'B', 'C', 'D']) ABCD 0 a 42.0 NaN NaN 1 b 52.0 NaN NaN 2 c NaN 31.0 NaN 3 d NaN 2.0 NaN 4 e NaN NaN 62.0 5 f NaN NaN 70.0 

Ahora me gustaría unir / combinar las columnas B, C y D a una nueva columna E como en este ejemplo:

 data2 = {'A': ['a', 'b', 'c', 'd', 'e', 'f'], 'E': [42, 52, 31, 2, 62, 70]} df2 = pd.DataFrame(data2, columns = ['A', 'E']) AE 0 a 42 1 b 52 2 c 31 3 d 2 4 e 62 5 f 70 

Encontré una pregunta bastante similar aquí, pero esto agrega las columnas B, C y D combinadas al final de la columna A:

 0 a 1 b 2 c 3 d 4 e 5 f 6 42 7 52 8 31 9 2 10 62 11 70 dtype: object 

Gracias por la ayuda.

Opción 1
Usando assign y drop

 In [644]: cols = ['B', 'C', 'D'] In [645]: df.assign(E=df[cols].sum(1)).drop(cols, 1) Out[645]: AE 0 a 42.0 1 b 52.0 2 c 31.0 3 d 2.0 4 e 62.0 5 f 70.0 

opcion 2
Usando la asignación y drop

 In [648]: df['E'] = df[cols].sum(1) In [649]: df = df.drop(cols, 1) In [650]: df Out[650]: AE 0 a 42.0 1 b 52.0 2 c 31.0 3 d 2.0 4 e 62.0 5 f 70.0 

Opción 3 Últimamente, me gusta la tercera opción.
Usando groupby

 In [660]: df.groupby(np.where(df.columns == 'A', 'A', 'E'), axis=1).first() #or sum max min Out[660]: AE 0 a 42.0 1 b 52.0 2 c 31.0 3 d 2.0 4 e 62.0 5 f 70.0 In [661]: df.columns == 'A' Out[661]: array([ True, False, False, False], dtype=bool) In [662]: np.where(df.columns == 'A', 'A', 'E') Out[662]: array(['A', 'E', 'E', 'E'], dtype='|S1') 

La pregunta tal como está escrita pide fusionar / combinar en lugar de sumr, así que publicar esto para ayudar a las personas que encuentran esta respuesta en busca de ayuda para unirse con combine_first, lo que puede ser un poco complicado.

 df2 = pd.concat([df["A"], df["B"].combine_first(df["C"]).combine_first(df["D"])], axis=1) df2.rename(columns={"B":"E"}, inplace=True) AE 0 a 42.0 1 b 52.0 2 c 31.0 3 d 2.0 4 e 62.0 5 f 70.0 

¿Qué es tan complicado con eso? en este caso, no hay problema, pero digamos que estaba extrayendo los valores B, C y D de diferentes marcos de datos, en los que estaban presentes las tags a, b, c, d, e, f, pero no necesariamente en el mismo orden. combine_first () se alinea con el índice, por lo que necesitaría colocar un set_index () en cada una de sus referencias df.

 df2 = pd.concat([df.set_index("A", drop=False)["A"], df.set_index("A")["B"]\ .combine_first(df.set_index("A")["C"])\ .combine_first(df.set_index("A")["D"]).astype(int)], axis=1).reset_index(drop=True) df2.rename(columns={"B":"E"}, inplace=True) AE 0 a 42 1 b 52 2 c 31 3 d 2 4 e 62 5 f 70 

Use la difference para los nombres de columnas sin A y luego obtenga sum o max :

 cols = df.columns.difference(['A']) df['E'] = df[cols].sum(axis=1).astype(int) # df['E'] = df[cols].max(axis=1).astype(int) df = df.drop(cols, axis=1) print (df) AE 0 a 42 1 b 52 2 c 31 3 d 2 4 e 62 5 f 70 

Si hay múltiples valores por filas:

 data = {'A': ['a', 'b', 'c', 'd', 'e', 'f'], 'B': [42, 52, np.nan, np.nan, np.nan, np.nan], 'C': [np.nan, np.nan, 31, 2, np.nan, np.nan], 'D': [10, np.nan, np.nan, np.nan, 62, 70]} df = pd.DataFrame(data, columns = ['A', 'B', 'C', 'D']) print (df) ABCD 0 a 42.0 NaN 10.0 1 b 52.0 NaN NaN 2 c NaN 31.0 NaN 3 d NaN 2.0 NaN 4 e NaN NaN 62.0 5 f NaN NaN 70.0 cols = df.columns.difference(['A']) df['E'] = df[cols].apply(lambda x: ', '.join(x.dropna().astype(int).astype(str)), 1) df = df.drop(cols, axis=1) print (df) AE 0 a 42, 10 1 b 52 2 c 31 3 d 2 4 e 62 5 f 70 

También puedes usar ffill con iloc :

 df['E'] = df.iloc[:, 1:].ffill(1).iloc[:, -1].astype(int) df = df.iloc[:, [0, -1]] print(df) AE 0 a 42 1 b 52 2 c 31 3 d 2 4 e 62 5 f 70