Как создать новую таблицу в БД MySQL из кадра данных pandas

0

Недавно я перешел от использования SQLite для большей части моего хранения и управления данными MySQL. Я думаю, что я, наконец, получил правильные библиотеки, установленные для работы с Python 3.6, но теперь мне не удается создать новую таблицу из фреймворка данных в базе данных MySQL.

Вот библиотеки, которые я импортирую:

import pandas as pd
import mysql.connector
from sqlalchemy import create_engine

В моем коде я сначала создаю dataframe из файла CSV (здесь нет проблем).

def csv_to_df(infile):
    return pd.read_csv(infile)

Затем я устанавливаю соединение с базой данных MySQL, используя эту функцию def:

def mysql_connection():
    user = 'root'
    password = 'abc'
    host = '127.0.0.1'
    port = '3306'
    database = 'a001_db'
    engine = create_engine("mysql://{0}:{1}@{2}:{3}/{4}?charset=utf8".format(user, password, host, port, database))
    return engine

Наконец, я использую функцию pandas "to_sql" для создания таблицы базы данных в базе данных MySQL:

def df_to_mysql(df, db_tbl_name, conn=mysql_connection(), index=False):
    df.to_sql(con = conn, name = db_tbl_name, if_exists='replace', index = False)

Я запускаю код, используя эту строку:

df_to_mysql(csv_to_df(r'path/to/file.csv'), 'new_database_table')

В результате получается следующая ошибка:

InvalidRequestError: Could not reflect: requested table(s) not available in Engine(mysql://root:***@127.0.0.1:3306/a001_db?charset=utf8): (new_database_table)

Я думаю, это говорит мне, что я должен сначала создать таблицу в базе данных, прежде чем передавать данные в dataframe в эту таблицу, но я не на 100% уверен в этом. Независимо от того, я ищу способ создать таблицу в базе данных MySQL без ручного создания таблицы в первую очередь (у меня есть много CSV, каждый с полями 50+, которые должны быть загружены в виде новых таблиц в базе данных MySQL).

Какие-либо предложения?

  • 1
    использовать sqlalchemy, чтобы сначала создать оператор создания таблицы, прежде чем пытаться загрузить фрейм данных в эту таблицу?
  • 0
    Это, кажется, путь - я смог написать код, чтобы сначала автоматически сгенерировать таблицу mysql из df, а затем записать данные df в эту таблицу. Мне пришлось преодолеть несколько ошибок, таких как: безымянные столбцы csv, определяющие правильный тип данных для каждого поля в таблице mysql.
Теги:
pandas
dataframe
python-3.6

1 ответ

0
Лучший ответ

Я предложил подход, предложенный aws_apprentice, который должен был сначала создать таблицу, а затем записать данные в таблицу.

Приведенный ниже код сначала автоматически генерирует таблицу mysql из df (автоматически определяя имена таблиц и типы данных), а затем записывает данные df в эту таблицу.

Мне пришлось преодолеть пару икота, например: неназванные столбцы csv, определяющие правильный тип данных для каждого поля таблицы mysql.

Я уверен, что есть несколько других (лучше?) Способов сделать это, но это, похоже, работает.

import pandas as pd
from sqlalchemy import create_engine

infile = r'path/to/file.csv'
db = 'a001_db'
db_tbl_name = 'a001_rd004_db004'

'''
Load a csv file into a dataframe; if csv does not have headers, use the headers arg to create a list of headers; rename unnamed columns to conform to mysql column requirements
'''
def csv_to_df(infile, headers = []):
    if len(headers) == 0:
        df = pd.read_csv(infile)
    else:
        df = pd.read_csv(infile, header = None)
        df.columns = headers
    for r in range(10):
        try:
            df.rename( columns={'Unnamed: {0}'.format(r):'Unnamed{0}'.format(r)},    inplace=True )
        except:
            pass
    return df

'''
Create a mapping of df dtypes to mysql data types (not perfect, but close enough)
'''
def dtype_mapping():
    return {'object' : 'TEXT',
        'int64' : 'INT',
        'float64' : 'FLOAT',
        'datetime64' : 'DATETIME',
        'bool' : 'TINYINT',
        'category' : 'TEXT',
        'timedelta[ns]' : 'TEXT'}
'''
Create a sqlalchemy engine
'''
def mysql_engine(user = 'root', password = 'abc', host = '127.0.0.1', port = '3306', database = 'a001_db'):
    engine = create_engine("mysql://{0}:{1}@{2}:{3}/{4}?charset=utf8".format(user, password, host, port, database))
    return engine

'''
Create a mysql connection from sqlalchemy engine
'''
def mysql_conn(engine):
    conn = engine.raw_connection()
    return conn
'''
Create sql input for table names and types
'''
def gen_tbl_cols_sql(df):
    dmap = dtype_mapping()
    sql = "pi_db_uid INT AUTO_INCREMENT PRIMARY KEY"
    df1 = df.rename(columns = {"" : "nocolname"})
    hdrs = df1.dtypes.index
    hdrs_list = [(hdr, str(df1[hdr].dtype)) for hdr in hdrs]
    for i, hl in enumerate(hdrs_list):
        sql += " ,{0} {1}".format(hl[0], dmap[hl[1]])
    return sql

'''
Create a mysql table from a df
'''
def create_mysql_tbl_schema(df, conn, db, tbl_name):
    tbl_cols_sql = gen_tbl_cols_sql(df)
    sql = "USE {0}; CREATE TABLE {1} ({2})".format(db, tbl_name, tbl_cols_sql)
    cur = conn.cursor()
    cur.execute(sql)
    cur.close()
    conn.commit()

'''
Write df data to newly create mysql table
'''
def df_to_mysql(df, engine, tbl_name):
    df.to_sql(tbl_name, engine, if_exists='replace')

df = csv_to_df(infile)
create_mysql_tbl_schema(df, mysql_conn(mysql_engine()), db, db_tbl_name)
df_to_mysql(df, mysql_engine(), db_tbl_name)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню