web-dev-qa-db-fra.com

Comment écrire un cadre de données Pandas dans sqlite avec Index

J'ai une liste de données boursières extraites de Yahoo dans un pandas DataFrame (voir le format ci-dessous). La date sert d'index dans le DataFrame. Je veux écrire les données (y compris l'index) dans une base de données 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

D'après ma lecture du code write_frame de Pandas, il ne prend actuellement pas en charge l'écriture de l'index . J'ai essayé d'utiliser to_records à la place, mais j'ai rencontré le problème avec Numpy 1.6.2 et la date-heure . Maintenant, j'essaie d'écrire des nuplets en utilisant .itertuples, mais SQLite génère une erreur indiquant que le type de données n'est pas pris en charge (voir le code et le résultat ci-dessous). Je suis relativement nouveau dans Python, Pandas et Numpy, il est donc tout à fait possible que je manque quelque chose d’évident. Je pense que je rencontre un problème pour écrire une date/heure dans SQLite, mais je pense que je pourrais trop compliquer les choses. 

Je pense que je peut peux résoudre le problème en passant à Numpy 1.7 ou à la version de développement de Pandas, qui a un correctif publié sur GitHub. Je préférerais développer en utilisant des versions de logiciel - je suis novice dans ce domaine et je ne veux pas que les problèmes de stabilité créent davantage de confusion. 

Existe-t-il un moyen d'y parvenir en utilisant Python 2.7.2, Pandas 0.10.0 et Numpy 1.6.2? Peut-être en train de nettoyer les dates-heures? Je suis un peu au-dessus de ma tête, toute aide serait appréciée. 

Code:

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)

Résultat:

---------------------------------------------------------------------------
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.
22
jmatthewhouse

Dans les pandas récents, l'index sera sauvegardé dans la base de données (il fallait auparavant reset_index first).

Après les docs (établissement d’une connexion SQLite en mémoire):

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

Remarque: vous pouvez également passer un moteur SQLAlchemy ici (voir la fin de la réponse).)

Nous pouvons enregistrer price2 dans cnx:

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

Nous pouvons récupérer via read_sql:

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

Cependant, lorsqu'elles sont stockées (et récupérées), dates sont unicode plutôt que Timestamp. Pour reconvertir ce que nous avons commencé, nous pouvons utiliser pd.to_datetime:

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

Nous récupérons le même DataFrame que prices:

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)

Vous pouvez également utiliser un moteur SQLAlchemy :

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

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

Cela vous permet d'utiliser read_sql_table (qui ne peut être utilisé qu'avec 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
27
Andy Hayden

Malheureusement, pandas.io.write_frame n'existe plus dans les versions les plus récentes de Pandas en ce qui concerne la réponse acceptée actuellement. Par exemple, j'utilise des pandas 0.19.2. Vous pouvez faire quelque chose comme 

from sqlalchemy import create_engine

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

Et puis tour à tour, prévisualisez votre table avec ce qui suit:

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

Ci-dessous le code qui a fonctionné pour moi. J'ai pu l'écrire dans 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()
1
Keerthesh Kumar