2014-03-27 50 views
3

我使用df.to_sql(con=con_mysql, name='testdata', if_exists='replace', flavor='mysql')將數據框導出到mysql中。但是,我發現具有長字符串內容的列(如url)被截斷爲63位數字。我收到IPython的筆記本電腦下面的警告時,我出口:pandas to_sql截取我的數據

/usr/local/lib/python2.7/site-packages/pandas/io/sql.py:248:警告:數據被截斷列「網址」在第3行 cur.executemany(insert_query,數據)

有在同一風格不同行等警告。

有什麼我可以調整以正確導出完整的數據?我可以在mysql中設置正確的數據模式,然後導出到該模式。但我希望調整可以讓它直接從python工作。

+0

什麼版本的熊貓使用? – joris

+0

0.12.0,當我有問題。我剛剛升級到最新版本的pip安裝版本0.13.1。但從你的答案來看,這與0.12.0會有相同的問題。 – MichM

回答

8

如果您使用熊貓0.13.1以上,63位這一限制確實是硬編碼,因爲這一行的代碼,:https://github.com/pydata/pandas/blob/v0.13.1/pandas/io/sql.py#L278

作爲一種變通方法,你也許可以猴補丁該功能get_sqltype

from pandas.io import sql 

def get_sqltype(pytype, flavor): 
    sqltype = {'mysql': 'VARCHAR (63)', # <-- change this value to something sufficient higher 
       'sqlite': 'TEXT'} 

    if issubclass(pytype, np.floating): 
     sqltype['mysql'] = 'FLOAT' 
     sqltype['sqlite'] = 'REAL' 
    if issubclass(pytype, np.integer): 
     sqltype['mysql'] = 'BIGINT' 
     sqltype['sqlite'] = 'INTEGER' 
    if issubclass(pytype, np.datetime64) or pytype is datetime: 
     sqltype['mysql'] = 'DATETIME' 
     sqltype['sqlite'] = 'TIMESTAMP' 
    if pytype is datetime.date: 
     sqltype['mysql'] = 'DATE' 
     sqltype['sqlite'] = 'TIMESTAMP' 
    if issubclass(pytype, np.bool_): 
     sqltype['sqlite'] = 'INTEGER' 

    return sqltype[flavor] 

sql.get_sqltype = get_sqltype 

然後就是用你的代碼應該工作:

df.to_sql(con=con_mysql, name='testdata', if_exists='replace', flavor='mysql') 

從熊貓0.14中,SQL模塊是開始使用SQLAlchemy的引擎蓋下,和字符串被轉換爲SQLAlchemy的TEXT類型,至極被轉換到MySQL TEXT類型(和不VARCHAR),這也將允許您可以存儲更大的字符串長度超過63個數字:

engine = sqlalchemy.create_engine('mysql://scott:[email protected]/foo') 
df.to_sql('testdata', engine, if_exists='replace') 

只有當你還在用一個DBAPI連接,而不是SQLAlchemy的發動機,這個問題仍然存在,但該選項已被棄用,建議提供SQLAlchemy的發動機to_sql

+0

好,非常感謝joris! – MichM

+1

我在熊貓0.14中遇到同樣的問題。如果我正確理解代碼(https://github.com/pydata/pandas/blob/v0.14.0/pandas/io/sql.py#L847),它仍然是硬編碼爲varchar(63)。我不得不改變這個來讓它工作。 –

+0

這是否應該在github上報告爲問題?它已經? –

5

受@ joris的回答啓發,我決定將這個改變硬編碼到熊貓的源代碼中並重新編譯。

cd /usr/local/lib/python2.7/dist-packages/pandas-0.14.1-py2.7-linux-x86_64.egg/pandas/io 
sudo pico sql.py 

改變的線​​

'mysql': 'VARCHAR (63)', 

'mysql': 'VARCHAR (255)', 

然後重新編譯只是文件

sudo python -m py_compile sql.py

重新啓動了我的腳本並且_to_sql()函數寫了一個表。 (我預計重編譯會打破熊貓,但似乎沒有)

這裏是我的腳本來寫一個數據框到mysql,以供參考。

import pandas as pd 
import numpy as np 
import matplotlib.pyplot as plt 
import sqlalchemy 
from sqlalchemy import create_engine 
df = pd.read_csv('10k.csv') 
## ... dataframe munging 
df = df.where(pd.notnull(df), None) # workaround for NaN bug 
engine = create_engine('mysql://user:[email protected]:3306/dbname') 
con = engine.connect().connection 
df.to_sql("issues", con, 'mysql', if_exists='replace', index=True, index_label=None)