pandas to_sql 方法在日期列上出错
我有一个数据框,长得像这样:
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
我还有一个sqlite3数据库,里面有一个叫做fee_profit的表。
fee_profit表有4个字段:
- id - 整数 - 主键
- perf_period_id - 整数
- date - 日期
- profit - 实数
当我尝试把数据框写入数据库时(这里不显示数据库连接的部分):
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模型创建的。
1 个回答
更新: 从pandas 0.15版本开始,to_sql
可以支持将日期时间值写入sqlite连接和sqlalchemy引擎。所以下面提到的解决方法就不再需要了。
pandas 0.15版本将在即将到来的十月发布,这个功能已经合并到开发版本中。
上面提到的错误原因是因为df
的'date'列是datetime64
类型,而这个类型不被sqlite3支持。所以你需要先把它转换成字符串(sqlite没有自动处理这个,可能是个bug或者缺失的功能),或者转换成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来处理不同类型的数据库。如果你使用这个,它会自动将日期时间列转换成字符串:
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!)。