【问题标题】:pandas to_sql method gives error with date columnpandas to_sql 方法给出日期列错误
【发布时间】:2014-08-14 21:21:06
【问题描述】:

我有一个如下所示的数据框:

df = pd.DataFrame(index= pd.date_range('2014-01-01', periods=10))
df['date'] = df.index.map(lambda x: x.strftime('%d-%m-%Y'))
df['date'] = df.index
df['profit']= rand(10)
df['perf_period_id']=2

还有一个带有名为 fee_profit 的表的 sqlite3 数据库

fee_profit 有 4 个字段:

  • id - 整数 - 主键
  • perf_period_id - 整数
  • 日期 - 日期
  • 利润 - 真实

当我尝试将数据框写入数据库时​​(不显示数据库连接):

df.to_sql(name='fee_profit', index=False, con=db, if_exists='append')

我得到以下代码:

252     else:
253         data = [tuple(x) for x in frame.values.tolist()]
--> 254     cur.executemany(insert_query, data)
255 
256 
InterfaceError: Error binding parameter 0 - probably unsupported type.

没有传递主键(这可能是问题吗?)我把桌子弄得乱七八糟,看起来肯定是日期问题。尝试了在索引中传递日期的各种组合,也是字符串,一点用都没有。

知道我哪里出错了。在任何地方都找不到使用此方法的示例。

使用 Pandas 0.13.1 和 sqlite 3 2.6.0。数据库是通过django 1.6模型创建的

【问题讨论】:

  • 你用的是什么版本的熊猫?你是如何创建db的?
  • @joris Pandas 0.13.1 和 sqlite 3 2.6.0 也为问题添加了版本

标签: python sql sqlite pandas


【解决方案1】:

更新: 从 pandas 0.15 开始,to_sql 支持将两个 sqlite 连接写入日期时间值作为 sqlalchemy 引擎。因此,不再需要下面描述的解决方法。
Pandas 0.15 将于 10 月发布,该功能已合并到开发版中。


上述错误的原因是df'date'列是datetime64列,sqlite3不支持这种类型。因此,您应该首先将其转换为字符串(对于 sqlite,这不会自动完成可能是一个错误/缺失的功能),或者转换为 datetime.date 对象(由 sqlite3 识别,但它也会被转换为字符串因为 sqlite 没有日期时间类型)。

您在代码示例中使用df['date'] = df.index.map(lambda x: x.strftime('%d-%m-%Y')) 执行了此操作,但随后您再次使用df['date'] = df.index 覆盖了该列,所以这可能是您的代码示例中的错误。但是如果你先把它转换成字符串,它就可以工作:

df = pd.DataFrame(index= pd.date_range('2014-01-01', periods=10))
df['date'] = df.index.map(lambda x: x.strftime('%d-%m-%Y'))
df['profit']= rand(10)
df['perf_period_id']=2

df.to_sql(name='fee_profit', index=False, con=db, if_exists='append')

从 pandas 0.14 开始,主要的 sql 函数被重构为使用 sqlalchemy 来处理不同的数据库风格。如果您使用它,它将与 datetime 列一起正常工作(它会自动将其转换为字符串):

df = pd.DataFrame(index= pd.date_range('2014-01-01', periods=10))
df['profit']= rand(10)
df['perf_period_id']=2

import sqlalchemy
db2 = sqlalchemy.create_engine('...')
df.to_sql(name='fee_profit', index=False, con=db2, if_exists='append')

将来仍将支持使用普通的 sqlite 连接对象而不是 sqlalchemy 引擎,就像您所做的那样(但仅适用于 sqlite!)。

【讨论】:

  • 我做了一些额外的测试。如果只是用 df['date'] = datetime.date(2014,1,1) 填充日期 id 数据框。即它工作的日期对象似乎很难转换与熊猫数据框一起使用的 datetime64[ns] 对象
  • 谢谢。一夜之间做了一些阅读,并没有意识到 sqlite 没有日期对象。因为它在假装拥有一个方面做得很好!我的字符串代码现在可以正常工作,因为我已将其转换为与原始数据相同的表示形式
  • 啊,谢谢,有趣!是的,那么只有sqlite3 无法识别datetime64,因为datetime.date 有效。但它仍然会被转换为字符串,因此您可以选择将其转换为datetime.date(与df.index.date)或自己直接转换为字符串。
  • 由于某种原因,如果它位于对象列中,则会发生转换。我从我的数据框索引中获取日期,甚至不能用 .astype(datetime.date) 强制它,因为它仍然是 datetime64。字符串解决方法虽然有效。
  • Pandas 使用datetime64 作为保存日期时间值的标准方式。因此,根据您将其分配给列的方式,它会再次尝试将其转换为 datetime64(但 df['date'] = df.index.date 似乎保留了类型)
猜你喜欢
  • 2015-11-21
  • 2021-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-12
  • 1970-01-01
相关资源
最近更新 更多