【问题标题】:How to write Pandas dataframe to sqlite with Index如何使用索引将 Pandas 数据框写入 sqlite
【发布时间】:2022-02-24 17:26:45
【问题描述】:

我有一个从雅虎提取的股票市场数据列表,包含在 pandas DataFrame 中(请参见下面的格式)。日期用作 DataFrame 中的索引。我想将数据(包括索引)写入 SQLite 数据库。

             AAPL     GE
Date
2009-01-02  89.95  14.76
2009-01-05  93.75  14.38
2009-01-06  92.20  14.58
2009-01-07  90.21  13.93
2009-01-08  91.88  13.95

根据我对 Pandas 的 write_frame 代码的阅读,它是does not currently support writing the index。我尝试改用 to_records,但遇到了issue with Numpy 1.6.2 and datetimes。现在我正在尝试使用 .itertuples 编写元组,但 SQLite 会引发不支持数据类型的错误(请参见下面的代码和结果)。我对 Python、Pandas 和 Numpy 比较陌生,所以我完全有可能遗漏了一些明显的东西。我想我在尝试将日期时间写入 SQLite 时遇到了问题,但我认为我可能过于复杂了。

我想我也许可以通过升级到 Numpy 1.7 或 Pandas 的开发版本来解决这个问题,它在 GitHub 上发布了一个修复程序。我更喜欢使用软件的发布版本进行开发——我是新手,我不希望稳定性问题进一步混淆问题。

有没有办法使用 Python 2.7.2、Pandas 0.10.0 和 Numpy 1.6.2 来完成这项工作?也许以某种方式清理日期时间?我有点不知所措,任何帮助将不胜感激。

代码:

import numpy as np
import pandas as pd
from pandas import DataFrame, Series
import sqlite3 as db

# download data from yahoo
all_data = {}

for ticker in ['AAPL', 'GE']:
    all_data[ticker] = pd.io.data.get_data_yahoo(ticker, '1/1/2009','12/31/2012')

# create a data frame
price = DataFrame({tic: data['Adj Close'] for tic, data in all_data.iteritems()})

# get output ready for database export
output = price.itertuples()
data = tuple(output)

# connect to a test DB with one three-column table titled "Demo"
con = db.connect('c:/Python27/test.db')
wildcards = ','.join(['?'] * 3)
insert_sql = 'INSERT INTO Demo VALUES (%s)' % wildcards
con.executemany(insert_sql, data)

结果:

---------------------------------------------------------------------------
InterfaceError                            Traceback (most recent call last)
<ipython-input-15-680cc9889c56> in <module>()
----> 1 con.executemany(insert_sql, data)

InterfaceError: Error binding parameter 0 - probably unsupported type.

【问题讨论】:

  • 如果你只想把索引作为表中的一列,你就不能给你的DataFrame一个重复索引的列吗?

标签: python sqlite pandas


【解决方案1】:

在最近的 pandas 中,索引将保存在数据库中(以前您必须先reset_index)。

按照docs(在内存中设置SQLite连接):

import sqlite3
# Create your connection.
cnx = sqlite3.connect(':memory:')

注意:您也可以在此处传递 SQLAlchemy 引擎(见答案末尾)。

我们可以将price2保存到cnx

price2.to_sql(name='price2', con=cnx)

我们可以通过read_sql检索:

p2 = pd.read_sql('select * from price2', cnx)

但是,当存储(和检索)日期是unicode,而不是Timestamp。要转换回我们开始使用的内容,我们可以使用pd.to_datetime

p2.Date = pd.to_datetime(p2.Date)
p = p2.set_index('Date')

我们得到与prices相同的DataFrame:

In [11]: p2
Out[11]: 
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1006 entries, 2009-01-02 00:00:00 to 2012-12-31 00:00:00
Data columns:
AAPL    1006  non-null values
GE      1006  non-null values
dtypes: float64(2)

您也可以使用SQLAlchemy engine

from sqlalchemy import create_engine
e = create_engine('sqlite://')  # pass your db url

price2.to_sql(name='price2', con=cnx)

这允许您使用read_sql_table(只能与 SQLAlchemy 一起使用):

pd.read_sql_table(table_name='price2', con=e)
#         Date   AAPL     GE
# 0 2009-01-02  89.95  14.76
# 1 2009-01-05  93.75  14.38
# 2 2009-01-06  92.20  14.58
# 3 2009-01-07  90.21  13.93
# 4 2009-01-08  91.88  13.95

【讨论】:

  • 谢谢安迪,这是正确的。我想我需要从不同的角度来看待它,就是这样。
  • 这澄清了很多 + 让我更有效率。非常感谢。
  • 如果这样可以避免其他人的痛苦,write_frame 已被弃用,现在您需要使用pd.DataFrame.to_sql。请参阅 Wes 的回答(如下)。
  • @JulianDrago 感谢您的评论,我会更新。这个答案已有 6 年历史,所以它已经过时也就不足为奇了:我希望有一个脚本来标记已弃用的答案以进行编辑(这不是唯一的)。 :)
  • 在我看来 price2.to_sql(name='price2', con=cnx) 应该改为 price2.to_sql(name='price2', con=e)。否则price2 数据将如何首先到达与“传递您的数据库 url”相对应的磁盘 SQLite 数据库上,以便被read_sql_table 检索?无论如何,这对我有用。虽然我觉得令人费解的是,自 2013 年以来没有人对此发表过明显的评论。
【解决方案2】:

不幸的是,就当前接受的答案而言,pandas.io.write_frame 不再存在于最新版本的 Pandas 中。例如,我使用的是 pandas 0.19.2。你可以做类似的事情

from sqlalchemy import create_engine

disk_engine = create_engine('sqlite:///my_lite_store.db')
price.to_sql('stock_price', disk_engine, if_exists='append')

然后依次使用以下内容预览您的表格:

df = pd.read_sql_query('SELECT * FROM stock_price LIMIT 3',disk_engine)
df.head()

【讨论】:

    【解决方案3】:

    以下是对我有用的代码。我能够将其写入 SQLite DB。

    import pandas as pd
    import sqlite3 as sq
    data = <This is going to be your pandas dataframe>
    sql_data = 'D:\\SA.sqlite' #- Creates DB names SQLite
    conn = sq.connect(sql_data)
    cur = conn.cursor()
    cur.execute('''DROP TABLE IF EXISTS SA''')
    data.to_sql('SA', conn, if_exists='replace', index=False) # - writes the pd.df to SQLIte DB
    pd.read_sql('select * from SentimentAnalysis', conn)
    conn.commit()
    conn.close()
    

    【讨论】:

      【解决方案4】:

      使用 sqlite3 的最小示例

      基于Keertesh Kumar's answer

      将 df 写入 sqlite

      import pandas as pd
      import sqlite3 as sq
      
      df = pd.DataFrame({'col1': [1, 2], 'col2': [3, 4]})
      table_name = "test" # table and file name
      
      conn = sq.connect('{}.sqlite'.format(table_name)) # creates file
      df.to_sql(table_name, conn, if_exists='replace', index=False) # writes to file
      conn.close() # good practice: close connection
      

      读取sqlite到df

      conn = sq.connect('{}.sqlite'.format(table_name))
      df = pd.read_sql('select * from {}'.format(table_name), conn)
      conn.close()
      

      【讨论】:

        猜你喜欢
        • 2018-04-19
        • 1970-01-01
        • 1970-01-01
        • 2018-05-12
        • 2018-02-26
        • 2016-01-20
        • 1970-01-01
        • 2019-04-10
        • 2018-04-20
        相关资源
        最近更新 更多