es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Convierte el marco de datos en formato largo, eliminando filas y expandiendo otras.

Tengo un marco de datos para pivotar a una forma más larga:

import pandas as pd
import io

_1 = pd.read_csv(io.StringIO(
    """date;        origin; val_one; val_two; aaa; bbb; ccc; ddd; eee; fff
    10/11/2009;        aaa;       1;       0;   0;   0;   0;   0;   1;   0
    10/11/2009;        bbb;       0;       1;   1;   0;   0;   0;   0;   1
    10/11/2009;        ccc;       0;       1;   0;   0;   0;   0;   0;   0
    10/11/2009;        ddd;       0;       2;   0;   1;   1;   1;   0;   0"""),
    sep=";").set_axis(['date', 'origin', 'val_one', 'val_two',
            'aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'], axis=1)

Ahora quiero crear díadas origen-destino (filas aaa:fff). Las filas en las que no existe un destino (es decir, ninguna de las columnas de destino es 1, por ejemplo, la tercera fila, índice 2) deben eliminarse; las filas en las que existe más de un destino (por ejemplo, la segunda fila, índice 1, donde aaa es 1 y fff es una de las columnas de destino es1) deben convertirse en dos filas. La salida esperada es:

_2_targ = pd.read_csv(io.StringIO(
    """date;        origin; val_one; val_two; target
    10/11/2009;        aaa;       1;       0;    eee
    10/11/2009;        bbb;       0;       1;    aaa
    10/11/2009;        bbb;       0;       1;    fff
    10/11/2009;        ddd;       0;       2;    bbb
    10/11/2009;        ddd;       0;       2;    ccc
    10/11/2009;        ddd;       0;       2;    ddd"""),
sep=';').set_axis(['date', 'origin', 'val_one', 'val_two', 'target'])

He intentado usar pd.melt sin éxito (ver abajo) – esto crea todas las díadas, incluso las que no quiero mantener (porque ninguna columna de destino es 1).

_2 = pd.melt(_1,
             id_vars=['date', 'origin', 'val_one', 'val_two'],
             value_vars=['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'],
             var_name='target', value_name='tmp')

¿Qué me estoy perdiendo?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Puedes usar pd.melt para crear la columna objetivo y luego filtrar el dataframe resultante para mantener solo las filas donde el objetivo sea 1. Luego, puedes dividir las filas con múltiples objetivos en dos filas utilizando str.split y explode. Así es como puedes hacerlo:

    # crear columna objetivo
    _2 = pd.melt(_1,
                 id_vars=['fecha', 'origen', 'val_uno', 'val_dos'],
                 value_vars=['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'],
                 var_name='objetivo', value_name='tiene_objetivo')
    
    # filtrar para mantener las filas con objetivo
    _2 = _2[_2['tiene_objetivo']==1]
    
    # dividir las filas con múltiples objetivos
    _2['objetivo'] = _2['objetivo'].str.split('_')
    _2 = _2.explode('objetivo')
    
    # eliminar columna innecesaria
    _2 = _2.drop('tiene_objetivo', axis=1)
    
    # renombrar columnas para que coincidan con la salida esperada
    _2 = _2.rename(columns={'objetivo': 'objetivo'})
    

    Esto debería darte la salida esperada _2_targ.

Comments are closed.