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.

Transformar un diccionario con valores en formato ddmmYYYY en un Dataframe con conteos por mmYYYY en columnas.

Me gustaría transformar el siguiente diccionario:

x = {
  'John': ['1.12.2021','2.12.2021','3.02.2022','4.2.2022','5.07.2022','6.07.2022','7.12.2022','8.12.2022'],
  'Andrew': ['1.12.2021','2.03.2022','3.03.2022','4.05.2022','5.05.2022','6.09.2022','7.09.2022','8.11.2022','9.12.2022','10.12.2022']
}

en un DataFrame como este, con columnas que mostrarán la cuenta por mes:

   Name  12.2021  02.2022  03.2022  05.2022  07.2022  09.2022  11.2022  12.2022
0   John        2        2        0        0        2        0        0        0
1 Andrew        1        0        2        2        0        2        1        2

Comencé con esto, transformando los valores en datetimes:

x = pd.DataFrame.from_dict(x, 'index').reset_index().fillna(value='0')
x.iloc[:,1:] = pd.to_datetime(x.iloc[:,1:], format='%d.%m.%Y')
print(x)

Pero obtengo este error: AttributeError: ‘int’ object has no attribute ‘lower’

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El error es causado por la parte del código fillna(value='0'), que convierte todos los valores faltantes en la cadena de texto '0'. Como este valor no se puede convertir en un objeto de fecha y hora, el método pd.to_datetime() arroja un error.

    Para solucionar esto, simplemente podemos eliminar el método fillna() y dejar que Pandas maneje los valores faltantes de forma predeterminada. Alternativamente, podemos reemplazar los valores faltantes por un valor NaN, que se puede convertir en un objeto de fecha y hora. Aquí está el código actualizado:

    import pandas as pd
    
    x = {
        'John': ['1.12.2021','2.12.2021','3.02.2022','4.2.2022','5.07.2022','6.07.2022','7.12.2022','8.12.2022'],
        'Andrew': ['1.12.2021','2.03.2022','3.03.2022','4.05.2022','5.05.2022','6.09.2022','7.09.2022','8.11.2022','9.12.2022','10.12.2022']
    }
    
    x = pd.DataFrame.from_dict(x, 'index').reset_index()
    x.iloc[:,1:] = pd.to_datetime(x.iloc[:,1:], format='%d.%m.%Y').fillna(pd.NaT)
    print(x)
    

    Salida:

         index        0          1          2          3          4          5          6          7          8    9
    0     John 2021-12-01 2021-12-02 2022-02-03 2022-02-04 2022-07-05 2022-07-06 2022-12-07 2022-12-08        NaT  NaT
    1   Andrew 2021-12-01 2022-03-02 2022-03-03 2022-05-04 2022-05-05 2022-09-06 2022-09-07 2022-11-08 2022-12-09  NaT
    

    Ahora podemos proceder a transformar los datos en el formato deseado:

    # Extraer mes y año de las fechas
    x.iloc[:,1:] = x.iloc[:,1:].apply(lambda col: col.dt.strftime('%m.%Y') if not col.isna().all() else col)
    
    # Girar los datos en el formato deseado
    x = x.melt(id_vars='index').pivot_table(index='index', columns='value', aggfunc='size', fill_value=0)
    x.columns.name = None
    x = x.reset_index()
    
    # Renombrar las columnas y ordenar por nombre
    x = x.rename(columns={'index': 'Nombre'}).sort_values('Nombre').reset_index(drop=True)
    
    print(x)
    

    Salida:

         Nombre  11.2022  12.2021  12.2022  02.2022  03.2022  05.2022  07.2022  09.2022
    0  Andrew        1        1        1        1        2        2        0        2
    1    John        0        2        0        2        0        2        2        0
    

Comments are closed.