将 Pandas 数据帧随时间附加到 SQLite3 数据库并返回

Dav*_*e X 5 python sqlite datetime timestamp pandas

我正在尝试这个:

import pandas as pd
import sqlite3
import datetime, pytz

#nowtime=datetime.datetime.now(pytz.utc)
nowtime=datetime.datetime.now()

print(nowtime)
df = pd.DataFrame(columns=list('ABCD'))
df.loc[0]=(3,0.141,"five-nine",nowtime)
df.loc[1]=(1,0.41,"four-two",nowtime)

print(df)

db = sqlite3.connect(':memory:')
c = db.cursor()
c.execute('create table if not exists ABCD ( A integer, B real, C text, D timestamp );')
c.execute('insert into ABCD (A,B,C, D) values (?,?,?,?);',(1,2.2,'4',nowtime))
c.executemany('insert into ABCD (A,B,C, D) values (?,?,?,?);',df.to_records(index=False))

db.commit()

print(pd.read_sql('select * from ABCD;',db))
Run Code Online (Sandbox Code Playgroud)

并得到这个:

 2018-03-07 19:09:58.584953
   A      B          C                          D
0  3  0.141  five-nine 2018-03-07 19:09:58.584953
1  1  0.410   four-two 2018-03-07 19:09:58.584953
   A      B          C                           D
0  1  2.200          4  2018-03-07 19:09:58.584953
1  3  0.141  five-nine    b'\xa8hx?\t\xb9\x19\x15'
2  1  0.410   four-two    b'\xa8hx?\t\xb9\x19\x15'
Run Code Online (Sandbox Code Playgroud)

理想情况下,我想将一些带有时间戳的数据推送到 sqlite3 中,并将其恢复回 pandas/python/numpy 中。

我已经看到通过主键将 Pandas 数据帧附加到 sqlite 表进行附加,但我不确定如何使用 sqlite3 使用 datetime.datetime、pandas Timestamps 或 numpy.datetime64 次。

另外,还有如何从 sqlite 读取日期时间作为日期时间而不是 Python 中的字符串?但我不知道如何在熊猫中做到这一点。

我花了很多时间的一件事是/sf/answers/1534137741/和令人困惑的多个 to_datetime() 。

使用 times、sqlite3 和 pandas 的好方法是什么?

####### 更新:

我尝试了这些改变:

db = sqlite3.connect(':memory:',detect_types=sqlite3.PARSE_DECLTYPES)

#...
for index,row in df.iterrows():
    print(row)
    c.execute('insert into ABCD (A,B,C,D) values (?,?,?,?);',(row.A,row.B,row.C,row.D.to_pydatetime()))


x = pd.read_sql('select *  from ABCD;',db)

print('Type of a pd.read_sql(SQLite3) timestamp  : ',type(x['D'][0]))

x = c.execute('select * from ABCD').fetchall()

print(x)
print('Type of a sqlite.execute(SQLite3) timestamp  : ',type(x[0][3]))
Run Code Online (Sandbox Code Playgroud)

使用 SQLite3 数据类型并测试返回值:

Type of a pd.read_sql(SQLite3) timestamp  :  <class 'pandas._libs.tslib.Timestamp'>
[(1, 2.2, '4', datetime.datetime(2018, 3, 8, 14, 46, 2, 520333)), (3, 141.0, 'five-nine', datetime.datetime(2018, 3, 8, 14, 46, 2, 520333)), (1, 41.0, 'four-two', datetime.datetime(2018, 3, 8, 14, 46, 2, 520333))]
Type of a sqlite.execute(SQLite3) timestamp  :  <class 'datetime.datetime'>
Run Code Online (Sandbox Code Playgroud)

另外,当我尝试datetime.datetime.now(pytz.utc)获取 UTC 感知时间时,但它破坏了很多东西。datetime.datetime.utcnow()通过返回不受时区影响的非时区感知对象,使用效果更好。

另请注意有关该参数的 Python sqlite3 文档sqlite3.connect(detect_types=...)。启用detect_types=PARSE_DECLTYPES|PARSE_COLNAMES提示 python 对系统之间传递的数据运行转换器。

Par*_*ait 3

问题源自 pandas' to_records(),它将日期时间字段转换为带有 T 分隔符的 ISO 时间戳:

print(df.to_records(index=False))
# [(3, 0.141, 'five-nine', '2018-03-07T20:40:39.808427000')
#  (1, 0.41 , 'four-two', '2018-03-07T20:40:39.808427000')]
Run Code Online (Sandbox Code Playgroud)

考虑将日期时间列转换为字符串,然后运行cursor executemany()

df.D = df.D.astype('str')

print(df.to_records(index=False))
# [(3, 0.141, 'five-nine', '2018-03-07 20:40:39.808427')
#  (1, 0.41 , 'four-two', '2018-03-07 20:40:39.808427')]
Run Code Online (Sandbox Code Playgroud)

共:

db = sqlite3.connect(':memory:')
c = db.cursor()
c.execute('create table if not exists ABCD ( A integer, B real, C text, D timestamp );')
c.execute('insert into ABCD (A,B,C, D) values (?,?,?,?);',(1,2.2,'4',nowtime))

df['D'] = df['D'].astype('str')
c.executemany('insert into ABCD (A,B,C, D) values (?,?,?,?);',df.to_records(index=False))

db.commit()
print(pd.read_sql('select * from ABCD;',db))

#    A      B          C                           D
# 0  1  2.200          4  2018-03-07 20:47:15.031130
# 1  3  0.141  five-nine  2018-03-07 20:47:15.031130
# 2  1  0.410   four-two  2018-03-07 20:47:15.031130
Run Code Online (Sandbox Code Playgroud)