2017-03-31 2 views
0

J'utilise python pour exporter une grande matrice (forme autour de 3000 * 3000) dans MySQL.Export Panda Dataframe ou tableau numpy à MySQL

En ce moment j'utilise MySQLdb pour insérer ces valeurs mais c'est trop gênant et trop inefficace. Voici mon code:

# -*- coding:utf-8 -*- 


import MySQLdb 
import numpy as np 
import pandas as pd 
import time 


def feature_to_sql_format(df): 
    df = df.fillna(value='') 
    columns = list(df.columns) 
    index = list(df.index) 
    index_sort = np.reshape([[int(i)] * len(columns) for i in index], (-1)).tolist() 
    columns_sort = (columns * len(index)) 
    values_sort = df.values.reshape(-1).tolist() 
    return str(zip(index_sort, columns_sort, values_sort))[1: -1].replace("'NULL'", 'NULL') 


if __name__ == '__main__': 
    t1 = time.clock() 
    df = pd.read_csv('C:\\test.csv', header=0, index_col=0) 
    output_string = feature_to_sql_format(df) 
    sql_CreateTable = 'USE derivative_pool;DROP TABLE IF exists test1;' \ 
         'CREATE TABLE test1(date INT NOT NULL, code VARCHAR(12) NOT NULL, value FLOAT NULL);' 
    sql_Insert = 'INSERT INTO test (date,code,value) VALUES ' + output_string + ';' 
    con = MySQLdb.connect(......) 
    cur = con.cursor() 
    cur.execute(sql_CreateTable) 
    cur.close() 
    cur = con.cursor() 
    cur.execute(sql_Insert) 
    cur.close() 
    con.commit() 
    con.close() 
    t2 = time.clock() 
    print t2 - t1 

Et il consomme environ 274 secondes totalement. Je me demandais s'il y avait une façon plus simple de faire cela, j'ai pensé à exporter la matrice vers csv et ensuite utiliser LOAD DATA INFILE pour importer, mais c'est aussi trop compliqué.

J'ai remarqué que dans pandas géants de documentation pandas dataframe a une to_sql fonction, et version 0.14 vous pouvez définir la 'saveur' à 'mysql', qui est:

df.to_sql(con=con, name=name, flavor='mysql') 

Mais maintenant, ma version de pandas géants est 0.19.2 et la saveur est réduite à seulement 'sqlite' ...... Et j'ai encore essayé d'utiliser

df.to_sql(con=con, name=name, flavor='sqlite') 

et il me donne une erreur.

Existe-t-il un moyen pratique de le faire?

+0

double possible de [écriture à la base de données MySQL avec l'aide de pandas géants SQLAlchemy, à \ _SQL] (http://stackoverflow.com/questions/30631325/écriture-à-mysql-base de données-avec-pandas-using-sqlalchemy-à-sql) – languitar

Répondre

1

versions ultérieures de pandas en charge les connecteurs sqlalchemy au lieu de flavor = "mysql"

D'abord, installer les dépendances:

pip install mysql-connector-python-rf==2.2.2 
pip install MySQL-python==1.2.5 
pip install SQLAlchemy==1.1.1 

Ensuite, créez le moteur:

from sqlalchemy import create_engine 
connection_string= "mysql+mysqlconnector://root:@localhost/MyDatabase" 
engine = create_engine(connection_string) 

vous pouvez utiliser df.to_sql(...):

df.to_sql('MyTable', engine) 

Voici quelques choses que vous pouvez faire à MYSQL pour accélérer votre chargement de données:

SET FOREIGN_KEY_CHECKS = 0; 
SET UNIQUE_CHECKS = 0; 
SET SESSION tx_isolation='READ-UNCOMMITTED'; 
SET sql_log_bin = 0; 
#LOAD DATA LOCAL INFILE.... 
SET UNIQUE_CHECKS = 1; 
SET FOREIGN_KEY_CHECKS = 1; 
SET SESSION tx_isolation='READ-REPEATABLE'; 
+0

Merci cela fonctionne, mais le problème est que je l'ai essayé et il prend encore plus de temps! Existe-t-il un moyen de raccourcir ce processus? mon csv est d'environ 3000 * 3000 et il ne prend que 100M comme un fichier au format csv. Je ne comprends pas pourquoi ça prend si longtemps ... –

+0

@DirkPaul votre CSV a 3000 lignes et 3000 colonnes? – Sam

+0

Oui, mais c'était trop gros pour SQL donc je dois le transformer en un dimensionnel avec (numéro_colonne, numéro_colonne, valeur) –