2

I’m currently working in a project where I have to scrape a web page extracting data from tables. My goal is to save this information and apply some transformation to represent this data in a manner that my boss can understand it.

Right know I’m able to extract the information and save it in a nested dictionary (1) like this

dicionario = 
{

'38609-2023':
            [
                {'Folio': '6', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '20/03/2023', 'Fecha Trámite': 'Resolución', 'Trámite': 'DESE CUENTA', 'Des. Trámite': '210337-2023', 'Correlativo': 'Cuenta (Secretaria)', 'Salas': 'Bloqueado'},

              {'Folio': '5', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '17/03/2023', 'Fecha Trámite': 'Otro Tramite', 'Trámite': 'CERT. INHABILIDAD ART. 195 C.O.T', 'Des. Trámite': '209274-2023', 'Correlativo': 'Unidad Ingreso', 'Salas': 'Bloqueado'},

             {'Folio': '4', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '17/03/2023', 'Fecha Trámite': 'Otro Tramite', 'Trámite': 'CERT. INHABILIDAD ART. 196 C.O.T', 'Des. Trámite': '209273-2023', 'Correlativo': 'Unidad Ingreso', 'Salas': 'Bloqueado'},

             {'Folio': '2', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '17/03/2023', 'Fecha Trámite': 'Otro Tramite', 'Trámite': 'CERTIFICADO DE INGRESO', 'Des. Trámite': '209272-2023', 'Correlativo': 'Unidad Ingreso', 'Salas': 'Bloqueado'}
            ],
              
'38451-2023': 
            [
                  {'Folio': '5', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '20/03/2023', 'Fecha Trámite': 'Resolución', 'Trámite': 'DESE CUENTA', 'Des. Trámite': '210447-2023', 'Correlativo': 'Cuenta (Secretaria)', 'Salas': 'Bloqueado'},

                  {'Folio': '4', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '17/03/2023', 'Fecha Trámite': 'Otro Tramite', 'Trámite': 'CERT. INHABILIDAD ART. 195 C.O.T', 'Des. Trámite': '208820-2023', 'Correlativo': 'Unidad Ingreso', 'Salas': 'Bloqueado'},

                  {'Folio': '2', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '17/03/2023', 'Fecha Trámite': 'Otro Tramite', 'Trámite': 'CERTIFICADO DE INGRESO', 'Des. Trámite': '208819-2023', 'Correlativo': 'Unidad Ingreso', 'Salas': 'Bloqueado'}
            ]}

So with this i want to add a new inner key using the date key value 'Año' ('Año': '20/03/2023' , 'Año': '17/03/2023', etc) that is present in all the data.

To acomplish this i use this lines of code in the first dictionary (1):

new_dict={}
for keys, values in dicionario.items():
    if not keys in new_dict:
        new_dict[keys]={}
    for value in values:
        print(value['Año'], value, keys)
        try:
            new_dict[keys][value['Año']]
        except KeyError:
            new_dict[keys][value['Año']] = []
        new_dict[keys][value['Año']].append(value)

print(new_dict)

And the result will be:

{
'38609-2023': 
               {
                  '20/03/2023': [
                                    {'Folio': '6', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '20/03/2023', 'Fecha Trámite': 'Resolución', 'Trámite': 'DESE CUENTA', 'Des. Trámite': '210337-2023', 'Correlativo': 'Cuenta (Secretaria)', 'Salas': 'Bloqueado'
                                    }
                                ], 

                  '17/03/2023': [
                                    {'Folio': '5', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '17/03/2023', 'Fecha Trámite': 'Otro Tramite', 'Trámite': 'CERT. INHABILIDAD ART. 195 C.O.T', 'Des. Trámite': '209274-2023', 'Correlativo': 'Unidad Ingreso', 'Salas': 'Bloqueado'}, 
                                    {'Folio': '4', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '17/03/2023', 'Fecha Trámite': 'Otro Tramite', 'Trámite': 'CERT. INHABILIDAD ART. 196 C.O.T', 'Des. Trámite': '209273-2023', 'Correlativo': 'Unidad Ingreso', 'Salas': 'Bloqueado'}, 
                                    {'Folio': '2', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '17/03/2023', 'Fecha Trámite': 'Otro Tramite', 'Trámite': 'CERTIFICADO DE INGRESO', 'Des. Trámite': '209272-2023', 'Correlativo': 'Unidad Ingreso', 'Salas': 'Bloqueado'}
                                ]
               }, 

'38451-2023': 
                {
                   '20/03/2023': [
                                    {'Folio': '5', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '20/03/2023', 'Fecha Trámite': 'Resolución', 'Trámite': 'DESE CUENTA', 'Des. Trámite': '210447-2023', 'Correlativo': 'Cuenta (Secretaria)', 'Salas': 'Bloqueado'}

                                 ], 
                   
                   '17/03/2023': [
                                    {'Folio': '4', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '17/03/2023', 'Fecha Trámite': 'Otro Tramite', 'Trámite': 'CERT. INHABILIDAD ART. 195 C.O.T', 'Des. Trámite': '208820-2023', 'Correlativo': 'Unidad Ingreso', 'Salas': 'Bloqueado'}, 
                                    {'Folio': '2', 'Doc.': 'Descargar Documento', 'Anexo': '2023', 'Año': '17/03/2023', 'Fecha Trámite': 'Otro Tramite', 'Trámite': 'CERTIFICADO DE INGRESO', 'Des. Trámite': '208819-2023', 'Correlativo': 'Unidad Ingreso', 'Salas': 'Bloqueado'}]}}

After this i want to flatten the nested dictionary to make it more human readable

df = pd.DataFrame.from_dict(new_dict, orient="index").stack().to_frame()
final_df = pd.DataFrame(df[0].values.tolist(), index=df.index)
print(final_df)

The result is a dataframe like this

enter image description here

This is not bad at all... but i want to use the keys from rows to use it as columns and use the values to fill every new column

Columns 0 replace with : Folio Doc. Anexo Año Fecha Trámite Trámite Des. Trámite Correlativo Salas Estado

Columns 1 replace with : Folio Doc. Anexo Año Fecha Trámite Trámite Des. Trámite Correlativo Salas Estado

Columns 2 replace with : Folio Doc. Anexo Año Fecha Trámite Trámite Des. Trámite Correlativo Salas Estado

I tried to explain better with a little example

enter image description here

I tried using pd.Dataframe.from_dict as you can see in the post but it didint work. I also tried converting the nested dictionary to json and then use pd.json_normalize but i cant get what i want. Also using

Any idea what i can do?... Maybe make a lambda funcion in all the columns? i dont know really... i dont have to much expirencie. Help me please

Kevin Llanos
  • 35
  • 1
  • 4

2 Answers2

2

I think this can solve your problem.

Your problem is very similar to this topic below. Link: Nested dictionary to multiindex dataframe where dictionary keys are column labels

Just apply a little modification of the presented function in the above topic in your new dict and convert it in a data frame.

example code:

AdjustedDict = {(outerKey, innerKey): values[0] for outerKey, innerDict in new_dict.items() for innerKey, values in innerDict.items()}

visualizationDf = pd.DataFrame(AdjustedDict).T

print(visualizationDf)

EDIT:

I noted that is a little bit more complex than the solution above because you have a dictionary wich its items are lists of dictionaries.

Then you need to open that structures to make a data frame.

The loop below solves the problem but i neeed to create a new index k.

k=0
for outerKey, innerDict in new_dict.items():
    for innerKey, values in innerDict.items():
        if len(values) ==1:
            auxDict[(k,outerKey,innerKey)] = values[0]
        else: 
            
            for i in values:
                auxDict[(k,outerKey,innerKey)] = i
                k= k+1
        k=k+1
                


print(pd.DataFrame(auxDict).T)

Xavier
  • 66
  • 3
  • Even when the other answer is much simpler, this help me to understand how to manage the list of dicts in this nested dict. So thanks you a lot for your time. – Kevin Llanos Mar 23 '23 at 16:04
2

You could load your data directly into pandas:

df = pd.DataFrame(dicionario.items(), columns=["id", "data"]).explode("data")
>>> df
           id                                               data
0  38609-2023  {'Folio': '6', 'Doc.': 'Descargar Documento', ...
0  38609-2023  {'Folio': '5', 'Doc.': 'Descargar Documento', ...
0  38609-2023  {'Folio': '4', 'Doc.': 'Descargar Documento', ...
0  38609-2023  {'Folio': '2', 'Doc.': 'Descargar Documento', ...
1  38451-2023  {'Folio': '5', 'Doc.': 'Descargar Documento', ...
1  38451-2023  {'Folio': '4', 'Doc.': 'Descargar Documento', ...
1  38451-2023  {'Folio': '2', 'Doc.': 'Descargar Documento', ...

It has "json" in the name, but .json_normalize can unpack the nested data here:

>>> pd.json_normalize(df["data"])
  Folio                 Doc. Anexo         Año Fecha Trámite                           Trámite Des. Trámite          Correlativo      Salas
0     6  Descargar Documento  2023  20/03/2023    Resolución                       DESE CUENTA  210337-2023  Cuenta (Secretaria)  Bloqueado
1     5  Descargar Documento  2023  17/03/2023  Otro Tramite  CERT. INHABILIDAD ART. 195 C.O.T  209274-2023       Unidad Ingreso  Bloqueado
2     4  Descargar Documento  2023  17/03/2023  Otro Tramite  CERT. INHABILIDAD ART. 196 C.O.T  209273-2023       Unidad Ingreso  Bloqueado
3     2  Descargar Documento  2023  17/03/2023  Otro Tramite            CERTIFICADO DE INGRESO  209272-2023       Unidad Ingreso  Bloqueado
4     5  Descargar Documento  2023  20/03/2023    Resolución                       DESE CUENTA  210447-2023  Cuenta (Secretaria)  Bloqueado
5     4  Descargar Documento  2023  17/03/2023  Otro Tramite  CERT. INHABILIDAD ART. 195 C.O.T  208820-2023       Unidad Ingreso  Bloqueado
6     2  Descargar Documento  2023  17/03/2023  Otro Tramite            CERTIFICADO DE INGRESO  208819-2023       Unidad Ingreso  Bloqueado

We can copy the original index + id column and add it to the result:

df = pd.json_normalize(df["data"]).set_index(df.index).assign(id=df["id"])
>>> df
  Folio                 Doc. Anexo         Año Fecha Trámite                           Trámite Des. Trámite          Correlativo      Salas          id
0     6  Descargar Documento  2023  20/03/2023    Resolución                       DESE CUENTA  210337-2023  Cuenta (Secretaria)  Bloqueado  38609-2023
0     5  Descargar Documento  2023  17/03/2023  Otro Tramite  CERT. INHABILIDAD ART. 195 C.O.T  209274-2023       Unidad Ingreso  Bloqueado  38609-2023
0     4  Descargar Documento  2023  17/03/2023  Otro Tramite  CERT. INHABILIDAD ART. 196 C.O.T  209273-2023       Unidad Ingreso  Bloqueado  38609-2023
0     2  Descargar Documento  2023  17/03/2023  Otro Tramite            CERTIFICADO DE INGRESO  209272-2023       Unidad Ingreso  Bloqueado  38609-2023
1     5  Descargar Documento  2023  20/03/2023    Resolución                       DESE CUENTA  210447-2023  Cuenta (Secretaria)  Bloqueado  38451-2023
1     4  Descargar Documento  2023  17/03/2023  Otro Tramite  CERT. INHABILIDAD ART. 195 C.O.T  208820-2023       Unidad Ingreso  Bloqueado  38451-2023
1     2  Descargar Documento  2023  17/03/2023  Otro Tramite            CERTIFICADO DE INGRESO  208819-2023       Unidad Ingreso  Bloqueado  38451-2023

You can then set id/ano as the index:

>>> df.set_index(["id", "Año"])
                      Folio                 Doc. Anexo Fecha Trámite                           Trámite Des. Trámite          Correlativo      Salas
id         Año                                                                                                                                     
38609-2023 20/03/2023     6  Descargar Documento  2023    Resolución                       DESE CUENTA  210337-2023  Cuenta (Secretaria)  Bloqueado
           17/03/2023     5  Descargar Documento  2023  Otro Tramite  CERT. INHABILIDAD ART. 195 C.O.T  209274-2023       Unidad Ingreso  Bloqueado
           17/03/2023     4  Descargar Documento  2023  Otro Tramite  CERT. INHABILIDAD ART. 196 C.O.T  209273-2023       Unidad Ingreso  Bloqueado
           17/03/2023     2  Descargar Documento  2023  Otro Tramite            CERTIFICADO DE INGRESO  209272-2023       Unidad Ingreso  Bloqueado
38451-2023 20/03/2023     5  Descargar Documento  2023    Resolución                       DESE CUENTA  210447-2023  Cuenta (Secretaria)  Bloqueado
           17/03/2023     4  Descargar Documento  2023  Otro Tramite  CERT. INHABILIDAD ART. 195 C.O.T  208820-2023       Unidad Ingreso  Bloqueado
           17/03/2023     2  Descargar Documento  2023  Otro Tramite            CERTIFICADO DE INGRESO  208819-2023       Unidad Ingreso  Bloqueado
jqurious
  • 9,953
  • 1
  • 4
  • 14
  • This is what i want. You dont know how grateful i'm. I'm gonna write down this and study the approach that you use to manipulate the data. I'm studying pandas and your answer blow my mind. Greating from Chile! – Kevin Llanos Mar 23 '23 at 16:08
  • @KevinLlanos Yes, pandas has lots of useful tools for reshaping/manipulating - this is just the first approach that seemed simplest to me. Blessings from Ireland. – jqurious Mar 23 '23 at 17:54