【问题标题】:Python3, Pandas and MySQL index issuePython3、Pandas 和 MySQL 索引问题
【发布时间】:2017-12-30 07:27:26
【问题描述】:

我是 Python 新手,正在尝试学习一些基本的数据操作(主要重点是数据科学)。所以我仍然在掌握 Pandas 和其他一切。 我想要实现的是创建一个 DataFrame 并将其存储在 MySQL 数据库中。这是我的脚本(不起作用):

from sqlalchemy.types import VARCHAR
from sqlalchemy import create_engine
import pandas as pd
import numpy as np

frame = pd.DataFrame(np.random.random((4,4)),
                 index=['val1','val2','val3','val4'],
                 columns=['col1','col2','col3','col4'])
engine = create_engine('mysql+pymysql://user:password@localhost/python_samples')
frame.to_sql('rnd_vals', engine, dtype={'index':VARCHAR(5)})

当我尝试执行此操作时,我收到一条错误消息,指出 MySQL 不允许在没有长度的情况下创建 TEXT/BLOB 索引:

InternalError: (pymysql.err.InternalError) (1170, "BLOB/TEXT column 'index' used in key specification without a key length") [SQL: 'CREATE INDEX ix_rnd_vals_index ON rnd_vals (`index`)']

我相信我可以通过在 to_sql() 函数上指定 dtype 选项来解决这个问题,但它没有帮助。 我找到了一种方法,通过连接两个 DataFrame,一个带有值,另一个带有索引:

from sqlalchemy.types import VARCHAR
import pandas as pd
import numpy as np
from sqlalchemy import create_engine
frame = pd.DataFrame(np.random.random(25).reshape(5,5),
                 columns=['Jan','Feb','Mar','Apr','May'])
idxFrame = pd.DataFrame({'index':['exp1','exp2','exp3','exp4','exp5']})
frame = frame.join(idxFrame)
frame=frame.set_index('index')
    engine = create_engine('mysql+pymysql://user:password@localhost/python_samples')
frame.to_sql('indexes',engine,if_exists='replace', index_label='index',
         dtype={'index':VARCHAR(5)})

这按预期工作,但我真的怀疑这是制作这个的正确方法,有人可以帮助我吗?我做错了什么?

谢谢

【问题讨论】:

  • 很确定第一个示例中的问题是 Pandas 命名索引的方式与您的 dtype 映射之间的名称不匹配,但现在无法检查。
  • 给你的第一个例子,检查什么是frame.index.name
  • 谢谢 Ilja Everilä,解决了。索引名称实际上是“None”,所以当我将 dtype 从 {'index':VARCHAR(5)} 更改为 {'None':VARCHAR(5)} 时,它解决了问题!

标签: mysql python-3.x pandas indexing sqlalchemy


【解决方案1】:

对于遇到此问题的人,cmets 上的 Ilja Everilä 解决了这个问题。索引名称实际上是“None”,而不是“index”,所以当我从

更改 dtype 时
dtype={'index':VARCHAR(5)}

dtype={'None':VARCHAR(5)}

它解决了这个问题,并且在 MySQL 上创建了表:

CREATE TABLE `rnd_vals` (
  `index` text,
  `col1` double DEFAULT NULL,
  `col2` double DEFAULT NULL,
  `col3` double DEFAULT NULL,
  `col4` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

正如预期的那样。

谢谢大家!

【讨论】:

    【解决方案2】:

    我试图找到一种直接的方法让pandas直接导入索引。最后reset_index()似乎是最简单的方法:

    my_df.reset_index()
    my_df.to_sql(name='my_table', con=engine, index=False, if_exists='replace')
    

    【讨论】:

      【解决方案3】:

      与:

      frame.to_sql('rnd_vals', engine, dtype={'None':VARCHAR(5)})
      

      它正在给予:

      1170, "BLOB/TEXT 列 'index' 用于没有键长度的键规范") [SQL: 'CREATE INDEX ix_indexes_index ON 索引 (index)'] (此错误的背景:http://sqlalche.me/e/e3q8

      这解决了问题:

      frame.to_sql('indexes',engine,if_exists='replace', index_label='index',dtype={frame.index.name:VARCHAR(5)})
      

      【讨论】:

        【解决方案4】:

        您正在尝试从 text/blob 类型的列创建索引。在这种情况下,由于动态特性,MySQL 无法将唯一性赋予列。没有与此相关的长度。您可以在将数据框保存到 MySQL 时提供列的类型,或者(如果您不需要索引)只需创建 index=False

        【讨论】:

          【解决方案5】:

          尽可能使用VARCHAR(...) 而不是TEXT

          一般来说,索引TEXT 列是没有用的。

          我无法提供 sqlalchemy;我不熟悉它如何混淆 SQL 代码。

          【讨论】:

          • 这里的问题是,我在设置 dtype 时使用了 VARCHAR()(或者我相信),所以似乎 sqlalchemy 忽略了这一点。
          • <snide-remark> 又一个第三方软件阻碍的案例。 </snide-remark> 使用 sqlalchemy 提交错误报告。
          猜你喜欢
          • 2011-05-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-04
          • 1970-01-01
          • 2017-01-04
          • 2017-04-16
          相关资源
          最近更新 更多