Jor*_*zen 13 python sql pandas
我正在从各种来源(csv,xls,json等...)加载数据到Pandas数据帧,我想生成语句来创建和填充这个数据的SQL数据库.有谁知道这样做的方法?
我知道pandas有一个to_sql函数,但是它只适用于数据库连接,它不能生成字符串.
我想要的是采用这样的数据帧:
import pandas as pd
import numpy as np
dates = pd.date_range('20130101',periods=6)
df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=list('ABCD'))
Run Code Online (Sandbox Code Playgroud)
并且会生成一个函数(这个例子是PostgreSQL,但任何都可以):
CREATE TABLE data
(
index timestamp with time zone,
"A" double precision,
"B" double precision,
"C" double precision,
"D" double precision
)
Run Code Online (Sandbox Code Playgroud)
jor*_*ris 20
如果您只想要'CREATE TABLE'的sql代码(而不是数据的插入),则可以使用get_schemapandas.io.sql模块的功能:
In [10]: print pd.io.sql.get_schema(df.reset_index(), 'data')
CREATE TABLE "data" (
"index" TIMESTAMP,
"A" REAL,
"B" REAL,
"C" REAL,
"D" REAL
)
Run Code Online (Sandbox Code Playgroud)
一些说明:
reset_index因为它不包括索引Jan*_*ang 20
SOURCE = df
TARGET = data
Run Code Online (Sandbox Code Playgroud)
def SQL_CREATE_STATEMENT_FROM_DATAFRAME(SOURCE, TARGET):
# SQL_CREATE_STATEMENT_FROM_DATAFRAME(SOURCE, TARGET)
# SOURCE: source dataframe
# TARGET: target table to be created in database
import pandas as pd
sql_text = pd.io.sql.get_schema(SOURCE.reset_index(), TARGET)
return sql_text
Run Code Online (Sandbox Code Playgroud)
CREATE TABLE语句字符串print('\n\n'.join(sql_text))
Run Code Online (Sandbox Code Playgroud)
def SQL_INSERT_STATEMENT_FROM_DATAFRAME(SOURCE, TARGET):
sql_texts = []
for index, row in SOURCE.iterrows():
sql_texts.append('INSERT INTO '+TARGET+' ('+ str(', '.join(SOURCE.columns))+ ') VALUES '+ str(tuple(row.values)))
return sql_texts
Run Code Online (Sandbox Code Playgroud)
INSERT INTO语句字符串print('\n\n'.join(sql_texts))
Run Code Online (Sandbox Code Playgroud)
小智 10
不确定这是否是绝对最好的方法,但这比使用更有效,df.iterrows()因为速度非常慢。nan此外,这还可以在正则表达式的帮助下处理值。
import re
def get_insert_query_from_df(df, dest_table):
insert = """
INSERT INTO `{dest_table}` (
""".format(dest_table=dest_table)
columns_string = str(list(df.columns))[1:-1]
columns_string = re.sub(r' ', '\n ', columns_string)
columns_string = re.sub(r'\'', '', columns_string)
values_string = ''
for row in df.itertuples(index=False,name=None):
values_string += re.sub(r'nan', 'null', str(row))
values_string += ',\n'
return insert + columns_string + ')\n VALUES\n' + values_string[:-2] + ';'
Run Code Online (Sandbox Code Playgroud)
如果您只是想生成一个带有基于插入的字符串pandas.DataFrame- 我建议使用 @rup 建议的批量 sql 插入语法。
这是我为此目的编写的函数的示例:
import pandas as pd
import re
def df_to_sql_bulk_insert(df: pd.DataFrame, table: str, **kwargs) -> str:
"""Converts DataFrame to bulk INSERT sql query
>>> data = [(1, "_suffixnan", 1), (2, "Noneprefix", 0), (3, "fooNULLbar", 1, 2.34)]
>>> df = pd.DataFrame(data, columns=["id", "name", "is_deleted", "balance"])
>>> df
id name is_deleted balance
0 1 _suffixnan 1 NaN
1 2 Noneprefix 0 NaN
2 3 fooNULLbar 1 2.34
>>> query = df_to_sql_bulk_insert(df, "users", status="APPROVED", address=None)
>>> print(query)
INSERT INTO users (id, name, is_deleted, balance, status, address)
VALUES (1, '_suffixnan', 1, NULL, 'APPROVED', NULL),
(2, 'Noneprefix', 0, NULL, 'APPROVED', NULL),
(3, 'fooNULLbar', 1, 2.34, 'APPROVED', NULL);
"""
df = df.copy().assign(**kwargs)
columns = ", ".join(df.columns)
tuples = map(str, df.itertuples(index=False, name=None))
values = re.sub(r"(?<=\W)(nan|None)(?=\W)", "NULL", (",\n" + " " * 7).join(tuples))
return f"INSERT INTO {table} ({columns})\nVALUES {values};"
Run Code Online (Sandbox Code Playgroud)
顺便说一句,它将nan/None条目转换为NULL并且可以将常量 column=value 对作为关键字参数传递(请参阅文档字符串示例中的status="APPROVED"和address=None参数)。
一般来说,它的工作速度更快,因为任何数据库都会为单个插入做很多工作:检查约束、构建索引、刷新、写入日志等。在执行多合一操作时,数据库可以优化这种复杂的操作,而不是一一调用引擎。
| 归档时间: |
|
| 查看次数: |
7042 次 |
| 最近记录: |