Saltar al contenido

Dividir múltiples columnas en filas en pandas dataframe

Después de mirar en diversos repositorios y foros de internet al final hemos hallado la solución que te compartimos más adelante.

Solución:

Tu puedes primero split columnas, crear Series por stack y elimine los espacios en blanco strip:

s1 = df.value.str.split(',', expand=True).stack().str.strip().reset_index(level=1, drop=True)
s2 = df.date.str.split(',', expand=True).stack().str.strip().reset_index(level=1, drop=True)

Entonces concat ambos Series a df1:

df1 = pd.concat([s1,s2], axis=1, keys=['value','date'])

Quitar columnas antiguas value y date y join:

print (df.drop(['value','date'], axis=1).join(df1).reset_index(drop=True))
  ticker      account value      date
0     aa       assets   100  20121231
1     aa       assets   200  20131231
2     bb  liabilities    50  20141231
3     bb  liabilities   150  20131231

Noto mucho esta pregunta. Es decir, ¿cómo divido esta columna que tiene una lista en varias filas? Lo he visto llamado explotar. A continuación se muestran algunos enlaces:

  • https://stackoverflow.com/a/38432346/2336654
  • https://stackoverflow.com/a/38499036/2336654

Entonces escribí una función que lo hará.

def explode(df, columns):
    idx = np.repeat(df.index, df[columns[0]].str.len())
    a = df.T.reindex_axis(columns).values
    concat = np.concatenate([np.concatenate(a[i]) for i in range(a.shape[0])])
    p = pd.DataFrame(concat.reshape(a.shape[0], -1).T, idx, columns)
    return pd.concat([df.drop(columns, axis=1), p], axis=1).reset_index(drop=True)

Pero antes de que podamos usarlo, necesitamos listas (o iterables) en una columna.

Configuración

df = pd.DataFrame([['aa', 'assets',      '100,200', '20121231,20131231'],
                   ['bb', 'liabilities', '50,50',   '20141231,20131231']],
                  columns=['ticker', 'account', 'value', 'date'])

df

ingrese la descripción de la imagen aquí

separar value y date columnas:

df.value = df.value.str.split(',')
df.date = df.date.str.split(',')

df

ingrese la descripción de la imagen aquí

Ahora podríamos explotar en cualquiera de las columnas o en ambas, una tras otra.

Solución

explode(df, ['value','date'])

ingrese la descripción de la imagen aquí


Momento

quite strip del tiempo de @ jezrael porque no pude agregarlo efectivamente al mío. Este es un paso necesario para esta pregunta ya que OP tiene espacios en cadenas después de las comas. Mi objetivo era proporcionar una forma genérica de explotar una columna dado que ya tiene iterables y creo que lo he logrado.

código

def get_df(n=1):
    return pd.DataFrame([['aa', 'assets',      '100,200,200', '20121231,20131231,20131231'],
                         ['bb', 'liabilities', '50,50',   '20141231,20131231']] * n,
                        columns=['ticker', 'account', 'value', 'date'])

pequeña muestra de 2 filas

ingrese la descripción de la imagen aquí

muestra mediana de 200 filas

ingrese la descripción de la imagen aquí

muestra grande de 2.000.000 filas

ingrese la descripción de la imagen aquí

escribí explode función basada en respuestas anteriores. Puede ser útil para cualquiera que quiera agarrarlo y usarlo rápidamente.

def explode(df, cols, split_on=','):
    """
    Explode dataframe on the given column, split on given delimeter
    """
    cols_sep = list(set(df.columns) - set(cols))
    df_cols = df[cols_sep]
    explode_len = df[cols[0]].str.split(split_on).map(len)
    repeat_list = []
    for r, e in zip(df_cols.as_matrix(), explode_len):
        repeat_list.extend([list(r)]*e)
    df_repeat = pd.DataFrame(repeat_list, columns=cols_sep)
    df_explode = pd.concat([df[col].str.split(split_on, expand=True).stack().str.strip().reset_index(drop=True)
                            for col in cols], axis=1)
    df_explode.columns = cols
    return pd.concat((df_repeat, df_explode), axis=1)

ejemplo dado de @piRSquared:

df = pd.DataFrame([['aa', 'assets', '100,200', '20121231,20131231'],
                   ['bb', 'liabilities', '50,50', '20141231,20131231']],
                  columns=['ticker', 'account', 'value', 'date'])
explode(df, ['value', 'date'])

producción

+-----------+------+-----+--------+
|    account|ticker|value|    date|
+-----------+------+-----+--------+
|     assets|    aa|  100|20121231|
|     assets|    aa|  200|20131231|
|liabilities|    bb|   50|20141231|
|liabilities|    bb|   50|20131231|
+-----------+------+-----+--------+

Si eres capaz, eres capaz de dejar un escrito acerca de qué le añadirías a esta división.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *