Pandas讀取或存儲數據至Mysql


兩種鏈接方式

用DBAPI構建數據庫鏈接

import pymysql
import pandas as pd

con = pymysql.connect(host="127.0.0.1",user="root",password="password",db="world")
# 讀取sql
data_sql=pd.read_sql("SQL查詢語句",con)
# 存儲
data_sql.to_csv("test.csv")

用sqlalchemy構建數據庫鏈接

import pandas as pd
import sqlalchemy
from sqlalchemy import create_engine

# 用sqlalchemy構建數據庫鏈接engine
db_info = {'user':'user', 
'password':'pwd', 
'host':'localhost', 
'database':'xx_db' # 這里我們事先指定了數據庫,后續操作只需要表即可
} 
engine = create_engine('mysql+pymysql://%(user)s:%(password)s@%(host)s/%(database)s?charset=utf8' % db_info,encoding='utf-8') #這里直接使用pymysql連接,echo=True,會顯示在加載數據庫所執行的SQL語句。
# sql 命令
sql_cmd = "SELECT * FROM table"
df = pd.read_sql(sql=sql_cmd, con=engine)

 

從Mysql讀取數據,返回DataFrame格式的數據

read_sql

pandas.read_sql(sql, con, index_col=None, coerce_float=True, params=None, parse_dates=None, columns=None, chunksize=None)

效果:將SQL查詢或數據庫表讀入DataFrame。

官方關於參數的詳細介紹:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_sql.html

如何使用read_sql

來源:https://www.cnblogs.com/cymwill/p/8289367.html

下面兩個的作用又是相同的:

 

將DataFrame格式的數據存儲到Mysql

to_sql

DataFrame.to_sql(name, con, schema=None, if_exists='fail', index=True, index_label=None, chunksize=None, dtype=None,method=None)

下部分來源:https://www.jianshu.com/p/d615699ff254

我們從一個簡單的例子開始。在 mysql 數據庫中有一個 emp_data 表,假設我們使用 pandas DataFrame ,將數據拷貝到另外一個新表 emp_backup

import pandas as pd
from sqlalchemy import create_engine
import sqlalchemy

engine = create_engine('mysql+pymysql://user:password@localhost/stonetest?charset=utf8')
df = pd.read_sql('emp_master', engine)
df.to_sql('emp_backup', engine)

使用 mysql 的 describe 命令比較 emp_master 表和 emp_backup 表結構:

mysql> describe emp_master; +----------------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+-------------+------+-----+---------+-------+ | EMP_ID | int(11) | NO | PRI | NULL | | | GENDER | varchar(10) | YES | | NULL | | | AGE | int(11) | YES | | NULL | | | EMAIL | varchar(50) | YES | | NULL | | | PHONE_NR | varchar(20) | YES | | NULL | | | EDUCATION | varchar(20) | YES | | NULL | | | MARITAL_STAT | varchar(20) | YES | | NULL | | | NR_OF_CHILDREN | int(11) | YES | | NULL | | +----------------+-------------+------+-----+---------+-------+ 8 rows in set (0.00 sec) 

emp_backup 表結構:

mysql> describe emp_backup; +----------------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +----------------+------------+------+-----+---------+-------+ | index | bigint(20) | YES | MUL | NULL | | | EMP_ID | bigint(20) | YES | | NULL | | | GENDER | text | YES | | NULL | | | AGE | bigint(20) | YES | | NULL | | | EMAIL | text | YES | | NULL | | | PHONE_NR | text | YES | | NULL | | | EDUCATION | text | YES | | NULL | | | MARITAL_STAT | text | YES | | NULL | | | NR_OF_CHILDREN | bigint(20) | YES | | NULL | | +----------------+------------+------+-----+---------+-------+ 9 rows in set (0.00 sec) 

我們發現,to_sql() 並沒有考慮將 emp_master 表字段的數據類型同步到目標表,而是簡單的區分數字型和字符型,這是第一個問題,第二個問題呢,目標表沒有 primary key。因為 pandas 定位是數據分析工具,數據源可以來自 CSV 這種文本型文件,本身是沒有嚴格數據類型的。而且,pandas 數據 to_excel() 或者to_sql() 只是方便數據存放到不同的目的地,本身也不是一個數據庫升遷工具。

但如果我們需要嚴謹地保留原表字段的數據類型,以及保留 primary key,該怎么做呢?

使用 SQL 語句來創建表結構

如果數據源本身是來自數據庫,通過腳本操作是比較方便的。如果數據源是來自 CSV 之類的文本文件,可以手寫 SQL 語句或者利用 pandas get_schema() 方法,如下例:

import sqlalchemy

print(pd.io.sql.get_schema(df, 'emp_backup', keys='EMP_ID', 
   dtype={'EMP_ID': sqlalchemy.types.BigInteger(),
       'GENDER': sqlalchemy.types.String(length=20),
       'AGE': sqlalchemy.types.BigInteger(),
       'EMAIL':  sqlalchemy.types.String(length=50),
       'PHONE_NR':  sqlalchemy.types.String(length=50),
       'EDUCATION':  sqlalchemy.types.String(length=50),
       'MARITAL_STAT':  sqlalchemy.types.String(length=50),
       'NR_OF_CHILDREN': sqlalchemy.types.BigInteger()
       }, con=engine))

get_schema()並不是一個公開的方法,沒有文檔可以查看。生成的 SQL 語句如下:

CREATE TABLE emp_backup (
        `EMP_ID` BIGINT NOT NULL AUTO_INCREMENT,
        `GENDER` VARCHAR(20),
        `AGE` BIGINT,
        `EMAIL` VARCHAR(50),
        `PHONE_NR` VARCHAR(50),
        `EDUCATION` VARCHAR(50),
        `MARITAL_STAT` VARCHAR(50),
        `NR_OF_CHILDREN` BIGINT,
        CONSTRAINT emp_pk PRIMARY KEY (`EMP_ID`)
)

to_sql() 方法使用 append 方式插入數據

to_sql() 方法的 if_exists 參數用於當目標表已經存在時的處理方式,默認是 fail,即目標表存在就失敗,另外兩個選項是 replace 表示替代原表,即刪除再創建,append 選項僅添加數據。使用 append 可以達到要求。

import pandas as pd
from sqlalchemy import create_engine
import sqlalchemy

engine = create_engine('mysql+pymysql://user:password@localhost/stonetest?charset=utf8')
df = pd.read_sql('emp_master', engine)
# make sure emp_master_backup table has been created
# so the table schema is what we want
df.to_sql('emp_backup', engine, index=False, if_exists='append')

也可以在 to_sql() 方法中,通過 dtype 參數指定字段的類型,然后在 mysql 中 通過 alter table 命令將字段 EMP_ID 變成 primary key。

df.to_sql('emp_backup', engine, if_exists='replace', index=False,
          dtype={'EMP_ID': sqlalchemy.types.BigInteger(),
                 'GENDER': sqlalchemy.types.String(length=20),
                 'AGE': sqlalchemy.types.BigInteger(),
                 'EMAIL':  sqlalchemy.types.String(length=50),
                 'PHONE_NR':  sqlalchemy.types.String(length=50),
                 'EDUCATION':  sqlalchemy.types.String(length=50),
                 'MARITAL_STAT':  sqlalchemy.types.String(length=50),
                 'NR_OF_CHILDREN': sqlalchemy.types.BigInteger()
                 })

with engine.connect() as con:
    con.execute('ALTER TABLE emp_backup ADD PRIMARY KEY (`EMP_ID`);')

當然,如果數據源本身就是 mysql,當然不用大費周章來創建數據表的結構,直接使用 create table like xxx 就行。以下代碼展示了這種用法:

import pandas as pd 
from sqlalchemy import create_engine

engine = create_engine('mysql+pymysql://user:password@localhost/stonetest?charset=utf8')
df = pd.read_sql('emp_master', engine)

# Copy table structure
with engine.connect() as con:
    con.execute('DROP TABLE if exists emp_backup')
    con.execute('CREATE TABLE emp_backup LIKE emp_master;')

df.to_sql('emp_backup', engine, index=False, if_exists='append')


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM