[Pandas] Dataframe
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
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:
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.
e anche qui devo poi capire come procedere ma questo poi....
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


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:
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.
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....
Risposte
Non è necessario passare da un dizionario per caricare dei dati da un database a un DataFrame Pandas. Puoi per esempio leggere come fare in [url=https://medium.com/jbennetcodes/how-to-use-pandas-to-access-databases-e4e74e6a329e#:~:text=%20How%20to%20use%20Pandas%20to%20access%20databases,joins.%20Any%20time%20you%20think%20of...%20More%20]questo articolo[/url].
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.
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.
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:
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
Ti riporto il codice funzionante senza e con l'aggiunta (???) fatta ma non so se può andare bene:
Codice funzionante senza
Codice funzionante con parte aggiunta che mi ricarica il dataframe
Cosa ne pensi?
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
Ti spiego:
Il database è online ma non è un file da scaricare bensì una pagina web che leggo con Pandas in questo modo:
pd.read_htmlricercando 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
ULC.UltimateListCtrldevo 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
# 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?
# 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
Qualcuno mi potrebbe spiegare come poter inserire nel caso la semaforica WAIT e SIGNAL ?
Li guardai brevemente anni fa ma per me incomprensibili non potendone verificare/testare il codice


Li guardai brevemente anni fa ma per me incomprensibili non potendone verificare/testare il codice



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.
Come poter risolvere? Grazie
Io vorrei che man mano che il DF aumenta di lunghezza, il ciclo aumenti il suo STOP.
for i in range(len(df_prot_gen)):
Come poter risolvere? Grazie
In questo modo ottengo ciò che voglio:
Può andare come codice? Grazie
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
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é [tt]self.datadata_m[/tt] è un dizionario se le suo chiavi sono interi consecutivi? Perché riscrivi completamente la tua tabella ad ogni iterazione?
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é [tt]self.datadata_m[/tt] è un dizionario se le suo chiavi sono interi consecutivi? Perché riscrivi completamente la tua tabella ad ogni iterazione?
il dizionario nel Thread0 è inizializzato in questo modo
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
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
..
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
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
..
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.
Devo aggiungere ora questo secondo dizionario a self.datadata_m per poi procedere alla scritture come nel codice precedentemente
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?
(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
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.
self.datadata_m = (N,)
Devo aggiungere ora questo secondo dizionario a self.datadata_m per poi procedere alla scritture come nel codice precedentemente
# 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?

(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

Ho modificato e semplificato il codice del Thread1 in questo modo:
Aggiorno il dizionario ma dopo qualche riga mi segnala questo msg:
Come posso risolvere? Grazie
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:
for key_m, data_m in datadata_m.items(): RuntimeError: dictionary changed size during iteration
Come posso risolvere? Grazie
Ciao ragazzi. Ringrazio anticipatamente @apatriarca per lo spunto.
Ho semplificato ulteriormente in questo modo: scrivo il dizionario riga oer riga nella tabella del mio notebook aggiornando contemporan il dizionario.
Può andare bene così? Grazie
Devo testarlo con una connessione internet più veloce.
Ho semplificato ulteriormente in questo modo: scrivo il dizionario riga oer riga nella tabella del mio notebook aggiornando contemporan il dizionario.
Può andare bene così? Grazie
for i in range(nx.number_of_nodes(Gr_)): self.itemDataMap_m = dict() datadata_m = prot_gen_list data_m = datadata_m[i] self.table_m.InsertStringItem(i, " ") data=[] ; data.append(N[i]) [data.append(data_m[j]) for j in range(0, len(data_m))] for jj in range(0, len(data)): self.table_m.SetStringItem(i, jj, str(data[jj])) self.table_m.SetItemData(i, i) self.itemDataMap_m[i] = (data) datadata_m = prot_gen_list time.sleep(1.2)
Devo testarlo con una connessione internet più veloce.