随着时间的推移将Pandas数据帧附加到SQLite3数据库&背部

时间:2018-03-08 00:12:18

标签: python pandas datetime sqlite timestamp

我正在尝试这个:

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))

得到这个:

 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'

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

我已经看到Appending Pandas dataframe to sqlite table by primary key要追加,但我不确定如何使用datetime.datetime,pandas时间戳或numpy.datetime64次使用sqlite3。

此外,还有How to read datetime back from sqlite as a datetime instead of string in Python?,但我无法弄清楚如何在熊猫中做到这一点。

我花了很多时间的一件事是https://stackoverflow.com/a/21916253/1653571和令人困惑的多个to_datetime()s。

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

####### update:

我尝试了这些改变:

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]))

使用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'>

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

还请注意sqlite3.connect(detect_types=...)参数上的Python sqlite3文档。启用detect_types=PARSE_DECLTYPES|PARSE_COLNAMES cues python以在系统之间传递的数据上运行转换器。

2 个答案:

答案 0 :(得分:2)

主要问题是SQLite没有datetime数据类型。

读取SQLite时,

PARSE_DECLTYPES无法帮助,因为SQLite中声明的列数据类型永远不会是日期时间。

由于您可以控制Pandas数据帧,因此您可以了解将它们保存回SQLite的时间点。

您正在使用的read_sql方法......

  

是read_sql_table和read_sql_query(和。)的便捷包装器   为了向后兼容)并将委托给特定的功能   取决于提供的输入(数据库表名称或SQL查询)。

在您的示例中,您提供了一个查询,因此它委托给read_sql_query方法https://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_sql_query.html#pandas.read_sql_query

这个参数parse_dates可以是:

  

{column_name:arg dict}的词典,其中arg dict对应于   pandas.to_datetime()的关键字参数特别有用   没有本机日期时间支持的数据库,例如SQLite

由于您事先知道哪些列是数据类型,因此您可以将这些列存储为具有与parse_dates期望的结果匹配的结构的dict,并将其传递到read_sql方法。

在我将pandas df保存回csv或其他文件的其他情况下,我使用了类似的东西来保存模式,以便在将csv加载回pandas时重新引入。 read_csv方法的dbtypes参数与下面的结构完全相同。

def getPandasSchema(df):
    ''' 
    takes a pandas dataframe and returns the dtype dictionary
    useful for applying types when reloading that dataframe from csv etc
    '''
    return dict(zip(df.columns.tolist(),df.dtypes.tolist()))

答案 1 :(得分:1)

问题源自大熊猫&#39; project.properties将您的日期时间字段转换为带有T分隔符的ISO时间戳:

sqlcl.setStmt(<SCRIPT  HERE>);
sqlcl.run();

考虑将datetime列转换为字符串,然后运行游标Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@//localhost:1521/XE","klrice","klrice"); //#get a DBUtil but won't actually use it in this example DBUtil util = DBUtil.getInstance(conn); //#create sqlcl ScriptExecutor sqlcl = new ScriptExecutor(conn); ByteArrayOutputStream bout = new ByteArrayOutputStream(); BufferedOutputStream buf = new BufferedOutputStream(bout); sqlcl.setOut(buf); //#setup the context ScriptRunnerContext ctx = new ScriptRunnerContext(); //#set the context sqlcl.setScriptRunnerContext(ctx); ctx.setBaseConnection(conn); //#change the format sqlcl.setStmt("@C:/Users/erkan.erkisi/Desktop/Jenkins/123.sql"); sqlcl.run(); String results = bout.toString("UTF8"); System.out.println(results);

to_records()

共:

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')]