2015-04-29 13 views
6

Ho un panda abbastanza grande dataframe - 50 o così intestazioni e poche centinaia di migliaia di righe di dati - e sto cercando di trasferire questi dati in un database usando il modulo ceODBC. In precedenza ero utilizzando pyodbc e l'utilizzo di una semplice dichiarazione di eseguire in un ciclo, ma questo è stato di prendere assurdamente lunghi (1000 record per 10 minuti) ...come trasformare il dataframe panda per l'inserimento tramite l'istruzione executemany()?

Ora sto provando un nuovo modulo e sto cercando di introdurre anche se executemany() io non sono abbastanza sicuro che cosa si intende con sequenza di parametri in:

cursor.executemany("""insert into table.name(a, b, c, d, e, f) 
values(?, ?, ?, ?, ?), sequence_of_parameters) 

dovrebbe apparire come un elenco costante lavoro attraverso l'intestazione di ogni come

['asdas', '1', '2014-12-01', 'true', 'asdasd', 'asdas', '2', 
'2014-12-02', 'true', 'asfasd', 'asdfs', '3', '2014-12-03', 'false', 'asdasd'] 
  • dove questo è un esempio di tre righe

o qual è il formato necessario?

come un'altra domanda correlata, come posso quindi convertire un normale dataframe panda in questo formato?

Grazie!

+0

Come vengono DFS collegate? Sono tutti sottoinsiemi dello stesso df più grande? È possibile unire, concat tutto e scrivere in DB in una volta, forse – EdChum

+0

Ciao Ed. È tutto un unico dataframe, ho pensato che dovessero essere riversati in sottoinsiemi di tutti i diversi header per lavorare all'interno della query ... quindi 'a', 'b', 'c' e così via sono lì per indicare diverse intestazioni di colonna per il dataframe –

+1

Hai provato a 'pymssql'? (ma non ho esperienza se questo è più veloce come 'pyodbc') Ma con questo puoi semplicemente usare il metodo pandas' to_sql' (il driver deve essere supportato da sqlalchemy per poterlo usare con i panda) – joris

risposta

5

Alla fine sono riuscito a capirlo. Quindi, se si dispone di un Pandas dataframe cui si desidera scrivere in un database utilizzando ceODBC, che è il modulo che ho usato, il codice è:

(con all_data i dataframe) valori mappa dataframe a stringa e memorizzare ogni riga come una tupla in una lista di tuple

for r in all_data.columns.values: 
    all_data[r] = all_data[r].map(str) 
    all_data[r] = all_data[r].map(str.strip) 
tuples = [tuple(x) for x in all_data.values] 

per la lista di tuple, cambiate tutti significanti valore nullo - che sono state catturate come stringhe di conversione sopra - in un tipo nullo che può essere passata al database fine. Questo era un problema per me, potrebbe non essere adatto a te.

string_list = ['NaT', 'nan', 'NaN', 'None'] 

def remove_wrong_nulls(x): 
    for r in range(len(x)): 
     for i,e in enumerate(tuples): 
      for j,k in enumerate(e): 
       if k == x[r]: 
        temp=list(tuples[i]) 
        temp[j]=None 
        tuples[i]=tuple(temp) 

remove_wrong_nulls(string_list) 

creare una connessione al database

cnxn=ceODBC.connect('DRIVER={SOMEODBCDRIVER};DBCName=XXXXXXXXXXX;UID=XXXXXXX;PWD=XXXXXXX;QUIETMODE=YES;', autocommit=False) 
cursor = cnxn.cursor() 

definire una funzione di trasformare la lista di tuple in un new_list che è un'ulteriore indicizzazione nella lista di tuple, in blocchi di 1000. Questo era necessario per me per passare i dati al database di cui Query SQL non può superare 1 MB.

def chunks(l, n): 
    n = max(1, n) 
    return [l[i:i + n] for i in range(0, len(l), n)] 

new_list = chunks(tuples, 1000) 

definire la query.

query = """insert into XXXXXXXXXXXX("XXXXXXXXXX", "XXXXXXXXX", "XXXXXXXXXXX") values(?,?,?)""" 

Run attraverso il il new_list contenente l'elenco delle tuple in gruppi di 1000 e di eseguire executemany.Seguire questa commettendo e chiudendo la connessione e il gioco è fatto :)

for i in range(len(new_list)): 
    cursor.executemany(query, new_list[i]) 
cnxn.commit() 
cnxn.close() 
+0

Questo codice è molto utile. – AppleGate0

5

Si può provare questo:

cursor.executemany(sql_str, your_dataframe.values.tolist()) 

Speranza che aiuta.

+1

Potresti si prega di elaborare più la tua risposta aggiungendo un po 'più di descrizione della soluzione che fornisci? – abarisone

2

potrebbe essere un po 'tardi per rispondere a questa domanda, ma forse può ancora aiutare qualcuno. executemany() non è implementato da molti ODBC. Uno di quelli che ce l'ha è MySQL. Quando si riferiscono alla sequenza di parametri significano:

parameters=[{'name':'Jorge', 'age':22, 'sex':'M'}, 
      {'name':'Karen', 'age':25, 'sex':'F'}, 
      {'name':'James', 'age':29, 'sex':'M'}] 

e per un'istruzione di query sarebbe simile al seguente:

SQL = INSERT IGNORE INTO WORKERS (NAME, AGE, SEX) VALUES (%(name)s, %(age)s, %(sex)s) 

che si presenta come ci sei arrivato. Un paio di cose anche se voglio segnalarlo nel caso in cui aiuti: panda ha una funzione to_sql che si inserisce in un db se viene fornito l'oggetto connettore e anche i dati.

di creare rapidamente una sequenza di parametri da un dataframe panda ho trovato i seguenti due metodi utili:

# creates list of dict, list of parameters 
# REF: https://groups.google.com/forum/#!topic/pydata/qna3Z3WmVpM 
parameters = [df.iloc[line, :].to_dict() for line in range(len(df))] 

# Cleaner Way 
parameters = df.to_dict(orient='records') 
+0

L'utilizzo dell'ultimo metodo per la creazione dell'elenco di dts fa in modo che i nomi delle colonne vengano ordinati alfabeticamente all'interno di ogni dict. Qualche idea su come ordinarli manualmente? –

+0

vuoi dire che i tasti nei dizionari sono ordinati alfabeticamente? le chiavi del dizionario non sono garantite per essere ordinate. Se vuoi che siano ordinati, devi usare un 'OrderedDict'. 'Df.to_dict (in = OrderedDict)' –