[Pandas] Dataframe

Messaggioda mic_1 » 11/05/2021, 16:37

Perdonate il generico titolo ma sinceramente non saprei nemmeno io come definirlo al meglio.
Mi spiego:

Sto catturando delle informazioni in un database online tramite un Thread daemon 0.
Inserisco le info che mi servono in un dizionario.
Questo dizionario lo devo poi richiamare in un altro Thread daemon 1 in fondo al programma.
Uso i Thread per velocizzare la ricerca e la scrittura nella tabella del visualizzatore che ho creato.

Ho pensato di convertire il dizionario (creato nel Thread daemon 0) in un DataFrame Pandas (convertirlo nel Thread daemon 1).
Ho effettuato la scrittura dei primi dati catturati. E fin qui tutto bene!!!!

Ora arriva il bello :lol: :-D
Vorrei in pratica scrivere le info nella tabella man mano che le scarica.

Sono riuscita a scrivere le prime informazioni ma avrei bisogno di aggiornare i DataFrame, catturare l'ultima riga e man mano scriverla.

Ho provato ad usare cicli while e for ma mi ripete n volte lo stesso DataFrame.
Ho provato ad inserire un contatore che carica il DataFrame +=1 ma purtroppo non riesco a trovare la soluzione.

Vorrei ricaricare/aggiornare il DataFrame ripetendo semplicemente questa istruzione in un ciclo ma non so come:
Codice:
df = pd.DataFrame.from_dict(dizionario)


Potreste aiutarmi?

Il dizionario non è completo per intenderci. Man mano che si riempie passa le info al DataFrame che mi risulta essere meglio strutturato per poi procedere alla scrittura.

Codice:
while True:
     df = pd.DataFrame.from_dict(dizionario)

oppure

jj = len(df)  # lunghezza del dataframe caricato in primis
while jj <= 350:
     df = pd.DataFrame.from_dict(dizionario)
     jj +=1
(Ho provato anche con il ciclo for ma in tutti i casi ricarica lo stesso numero di righe del df per n volte)

Ho usato questa istruzione per intercettare l'ultima riga caricata in df in modo da poter procedere con la scrittura:
df.tail(1)


e anche qui devo poi capire come procedere ma questo poi....
mic_1
Junior Member
Junior Member
 
Messaggio: 169 di 386
Iscritto il: 11/01/2011, 18:11

Re: [Pandas] Dataframe

Messaggioda apatriarca » 12/05/2021, 12:37

Non è necessario passare da un dizionario per caricare dei dati da un database a un DataFrame Pandas. Puoi per esempio leggere come fare in questo articolo.

Nel tuo ciclo for non stai modificando il dizionario per cui otterrai sempre lo stesso DataFrame. Personalmente passerei solo i nuovi dati tra i due thread e quindi concatenerei il DataFrame con tutti i dati vecchio con quello con i nuovi dati. Senza avere una idea migliore della tua applicazione è però difficile dirti qualcosa di più preciso.
apatriarca
Moderatore
Moderatore
 
Messaggio: 5550 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [Pandas] Dataframe

Messaggioda mic_1 » 12/05/2021, 14:00

Ciao Apatriarca, grazie per la risposta!
Ti spiego:
Il database è online ma non è un file da scaricare bensì una pagina web che leggo con Pandas in questo modo:
Codice:
  pd.read_html
ricercando l'informazione riga per riga e catturando quella che mi interessa.
Queste informazioni poi le inserisco in un dizionario ripulendole ovvero elimino i campi che mi riportano NAN.
Per poterle poi scrivere in una tabella da me creata di tipo
Codice:
  ULC.UltimateListCtrl
devo passare le informazioni per colonna e riga per riga verrà scritta.

Ti riporto il codice funzionante senza e con l'aggiunta (???) fatta ma non so se può andare bene:

Codice funzionante senza
Codice:
# Coverto il dizionario in DataFrame
df_prot_gen = pd.DataFrame.from_dict(prot_gen_list) 
print('lungh dataframe  ', len(df_prot_gen))
print(df_prot_gen)
lista=[] ; count=0
# Mi servono le colonne del datafame come liste di elementi
# per poter scrivere le i dati in tabella riga per riga
for k in prot_gen_list.keys():
     globals()["Molec_Type_" + str(count)] = df_prot_gen[k].tolist()
     count+=1
           
for i in range(len(df_prot_gen)):       
     print('len(df_prot_gen) AAA', len(df_prot_gen))
     self.datadata_m[i] = (N[i], Molec_Type_0[i], Molec_Type_1[i], Molec_Type_2[i],
                                    Molec_Type_3[i], Molec_Type_4[i], Molec_Type_5[i])

     # Provvedo alla scrittura di ciascuna riga nella table precedentemente definita
     # nel programma principale
     index_m = 0 ; lista_m = [] ; self.itemDataMap_m = dict()
     for key_m, data_m in self.datadata_m.items():
          self.table_m.InsertStringItem(index_m, " ")
          for j in range(len(data_m)):
               self.table_m.SetStringItem(index_m, j, str(data_m[j]))
               lista_m.append(data_m[j])
          self.table_m.SetItemData(index_m, key_m)   
          self.itemDataMap_m[index_m] = lista_m
          index_m += 1     


Codice funzionante con parte aggiunta che mi ricarica il dataframe
Cosa ne pensi?

Codice:
# Coverto il dizionario in DataFrame
df_prot_gen = pd.DataFrame.from_dict(prot_gen_list) 
print('lungh dataframe  ', len(df_prot_gen))
print(df_prot_gen)
lista=[] ; count=0
# Mi servono le colonne del datafame come liste di elementi
# per poter scrivere le i dati in tabella riga per riga
for k in prot_gen_list.keys():
     globals()["Molec_Type_" + str(count)] = df_prot_gen[k].tolist()
     count+=1
           
for i in range(len(df_prot_gen)):       
     print('len(df_prot_gen) AAA', len(df_prot_gen))
     self.datadata_m[i] = (N[i], Molec_Type_0[i], Molec_Type_1[i], Molec_Type_2[i],
                                    Molec_Type_3[i], Molec_Type_4[i], Molec_Type_5[i])

     # Provvedo alla scrittura di ciascuna riga nella table precedentemente definita
     # nel programma principale
     index_m = 0 ; lista_m = [] ; self.itemDataMap_m = dict()
     for key_m, data_m in self.datadata_m.items():
          self.table_m.InsertStringItem(index_m, " ")
          for j in range(len(data_m)):
               self.table_m.SetStringItem(index_m, j, str(data_m[j]))
               lista_m.append(data_m[j])
          self.table_m.SetItemData(index_m, key_m)   
          self.itemDataMap_m[index_m] = lista_m
          index_m += 1     

     # aggiorna il Dataframe e ripete il ciclo  PARTE AGGIUNTA
     print('ultima RIGA', df_prot_gen.tail(1))   
     df_prot_gen = pd.DataFrame.from_dict(prot_gen_list)
     print('len(df_prot_gen) BBB', len(df_prot_gen))
     if len(df_prot_gen) == nx.number_of_nodes(Gr_): break
     else: continue


Vedo che aggiunge ulteriore righe in scrittura table maaaa.... ad un certo punto si interrompe non so se per via della connessione poco veloce o meno. Devo verificare.

Secondo te questa parte di codice aggiunta può risolvere ? Grazie mille
mic_1
Junior Member
Junior Member
 
Messaggio: 170 di 386
Iscritto il: 11/01/2011, 18:11

Re: [Pandas] Dataframe

Messaggioda mic_1 » 12/05/2021, 15:49

Qualcuno mi potrebbe spiegare come poter inserire nel caso la semaforica WAIT e SIGNAL ? :| :roll:

Li guardai brevemente anni fa ma per me incomprensibili non potendone verificare/testare il codice :roll: :roll: :roll:
mic_1
Junior Member
Junior Member
 
Messaggio: 171 di 386
Iscritto il: 11/01/2011, 18:11

Re: [Pandas] Dataframe

Messaggioda mic_1 » 12/05/2021, 23:10

Ho testato meglio il codice e ho notato che il RANGE del ciclo FOR non incrementa automaticamente la lunghezza massima del DF.
Io vorrei che man mano che il DF aumenta di lunghezza, il ciclo aumenti il suo STOP.

Codice:
for i in range(len(df_prot_gen)):


Come poter risolvere? Grazie
mic_1
Junior Member
Junior Member
 
Messaggio: 172 di 386
Iscritto il: 11/01/2011, 18:11

Re: [Pandas] Dataframe

Messaggioda mic_1 » 13/05/2021, 09:45

In questo modo ottengo ciò che voglio:
Codice:

df_prot_gen = pd.DataFrame.from_dict(prot_gen_list) 
count=0
for k in prot_gen_list.keys():
    globals()["Molec_Type_" + str(count)] = df_prot_gen[k].tolist()
    #print("len(Molec_Type_" + str(count), len("Molec_Type_" + str(count)))
    count+=1

# Con il ciclo while aggiorno il DataFrame man mano che il Thread0
# cattura le informazioni dal sito UniProt
for i in range(nx.number_of_nodes(Gr_)):  #len(df_prot_gen)):       
    self.datadata_m[i] = (N[i], Molec_Type_0[i], Molec_Type_1[i], Molec_Type_2[i],
                        Molec_Type_3[i], Molec_Type_4[i], Molec_Type_5[i])
    # Provvedo alla scrittura di ciascuna riga nella table
    index_m = 0 ; lista_m = [] ; self.itemDataMap_m = dict()
    for key_m, data_m in self.datadata_m.items():
        self.table_m.InsertStringItem(index_m, " ")
        for j in range(0, len(data_m)):
            self.table_m.SetStringItem(index_m, j, str(data_m[j]))
            lista_m.append(data_m[j])
        self.table_m.SetItemData(index_m, key_m)   
        self.itemDataMap_m[index_m] = lista_m
        index_m += 1     
    # aggiorna il Dataframe e ripete il ciclo
    df_prot_gen2 = pd.DataFrame.from_dict(prot_gen_list)
    count=0
    for k in prot_gen_list.keys():
        globals()["Molec_Type_" + str(count)] = df_prot_gen2[k].tolist()
        count+=1
    time.sleep(0.5)
    if len(self.datadata_m) < len(df_prot_gen2) : pass
    else:
         print('presooo'
         time.sleep(1)
     print('len(df_prot_gen2) BBB', len(df_prot_gen2), len(self.datadata_m), N[i])
     continue
               


Può andare come codice? Grazie
mic_1
Junior Member
Junior Member
 
Messaggio: 173 di 386
Iscritto il: 11/01/2011, 18:11

Re: [Pandas] Dataframe

Messaggioda apatriarca » 15/05/2021, 17:33

Sinceramente non capisco il senso del codice. Ho l'impressione che ti stai complicando la vita senza alcun reale vantaggio.

Che framework grafico stai usando? In che formato è il dizionario che stai usando per inizializzare il DataFrame? C'è una ragione per passare ad un DataFrame invece di usare direttamente il dizionario? Il tuo dizionario è condiviso tra i due thread? Perché self.datadata_m è un dizionario se le suo chiavi sono interi consecutivi? Perché riscrivi completamente la tua tabella ad ogni iterazione?
apatriarca
Moderatore
Moderatore
 
Messaggio: 5554 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [Pandas] Dataframe

Messaggioda mic_1 » 17/05/2021, 11:50

il dizionario nel Thread0 è inizializzato in questo modo
Codice:
 prot_gen_list=collections.defaultdict(list)

Ho bisogno di trasformarlo in DataFrame per avere i dati per colonna e non per riga come nel dizionario.

Il dizionario è condiviso ma il Thread1 non interviene nella modifica dei dati ma semplicemente lo converte in DataFrame per poi provvedere alla scrittura.

self.datadata_m è un dizionario definito anch'esso in
Codice:
 self.datadata_m = collections.defaultdict(list)


Riscrivo completamente la tabella perchè la scrittura avviene riga per riga ma l'aggiornamento del dizionario dipende dal tipo di connessione internet che può essere più o meno veloce (Ho fatto delle prove con fibra ufficio e internet lento di casa (di tipo analogico) e ho notato che viene aggiornato a volte di riga in riga e a volte di più righe alla volta e non vorrei che qualcuna venisse saltata)

Capisco possa essere laborioso ma sinceramente non saprei come altro modo risolvere.
Come mi consigli procedere??? Grazie mille per il supporto

..
mic_1
Junior Member
Junior Member
 
Messaggio: 175 di 386
Iscritto il: 11/01/2011, 18:11

Re: [Pandas] Dataframe

Messaggioda mic_1 » 19/05/2021, 15:13

Sto provando a passare direttamente il dizionario prot_gen_list ovviamente costruito diversamente (se prima avevo stabilito che le keys erano esattamente i nomi delle colonne della tabella che andavo a leggere sul web, ora ho gli indici dei nodi, abbinati alla riga catturata per ciascun nodo). Questo nel Thread0

A questo punto, nel Thread1, vado ad aggiungere il dizionario di "tuple" al dizionario contenete i nomi dei nodi e per poi procedere alla scrittura di ciascuna riga sul mio Panel.
Codice:
self.datadata_m = (N,)

Devo aggiungere ora questo secondo dizionario a self.datadata_m per poi procedere alla scritture come nel codice precedentemente
Codice:
# Gen_Prot è la lista di elementi aggiunta al dizionario prot_gen_list
dict([ tuple(prot_gen_list[k][i] for k in range(len(Gen_Prot)))) for i in range(nx.number_of_nodes(Gr_)) ])


Ovviamente il dizionario prot_gen_list lo dovrò aggiornare man mano che procedo alla scrittura di riga per riga.
Cosa ne dici? E' meglio procedere in questo modo? Grazie

COME POSSO SCRIVERE LE RIGHE DEL MIO DIZIONARIO PER POI AGGIONARE IL DIZIONARIO DI PARTENZA, AGGIUNGERLO OGNI VOLTA A self.datadata_m E SCRIVERE IN CONTEMPORANEA LE RIGHE AGGIUNTIVE SENZA DOVER RISCRIVERE OGNI VOLTA L'INTERA TABELLA?? C'E' UN MODO? :lol:
(ho scritto in maiuscolo solo per metterlo in evidenza rispetto al resto del testo)

GRAZIE!!! Ah dimenticavo, uso WXPYTHON per la grafica



Sto trovando difficoltà nell'aggiunta del dizionario di tuple ;-)
mic_1
Junior Member
Junior Member
 
Messaggio: 176 di 386
Iscritto il: 11/01/2011, 18:11

Re: [Pandas] Dataframe

Messaggioda mic_1 » 19/05/2021, 21:34

Ho modificato e semplificato il codice del Thread1 in questo modo:
Codice:
            datadata_m = prot_gen_list
            # Provvedo alla scrittura di ciascuna riga nella table
            index_m = 0 ; self.itemDataMap_m = dict()
            for key_m, data_m in datadata_m.items():
                self.table_m.InsertStringItem(index_m, " ")
                data=[] ; data.append(N[index_m])
                [data.append(data_m[j]) for j in range(0, len(data_m))]
                for jj in range(0, len(data)):
                    self.table_m.SetStringItem(index_m, jj, str(data[jj]))
                    self.table_m.SetItemData(index_m, key_m)   
                self.itemDataMap_m[index_m] = (data)
                datadata_m = prot_gen        # punto in cui aggiorno il dizionario elaborato
                index_m += 1                          nel Thread0

Aggiorno il dizionario ma dopo qualche riga mi segnala questo msg:
Codice:
for key_m, data_m in datadata_m.items():
RuntimeError: dictionary changed size during iteration


Come posso risolvere? Grazie
mic_1
Junior Member
Junior Member
 
Messaggio: 177 di 386
Iscritto il: 11/01/2011, 18:11

Prossimo

Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite