2017-01-14 17 views
0

私はmysqlデータベースにデータを書きたいと思っていました。私はデータベースから現在のデータを読み込み、新しい値を計算しています。新しい値は、以下に示すようにデータベース内のデータと同じ順序で書き込まれる必要があります。私は既存のデータを上書きしたくありません。私はto_sqlを使用したくありません。mysqlデータベースにデータフレームを書き込む

Iは、次のエラーメッセージが表示されます

(mysql.connector.errors.DatabaseError)1265(01000):データは1行で列 'log_return' の を切り捨て[SQL:「

。INSERT INTOを

完全なコードは以下のとおりです。

import sqlalchemy as sqlal 
import pandas as pd 
import numpy as np 

mysql_engine = sqlal.create_engine(xxx) 
mysql_engine.raw_connection() 

metadata = sqlal.MetaData() 

product = sqlal.Table('product', metadata, 
         sqlal.Column('ticker', sqlal.String(10), primary_key=True, nullable=False, unique=True),     
         sqlal.Column('isin', sqlal.String(12), nullable=True), 
         sqlal.Column('product_name', sqlal.String(80), nullable=True), 
         sqlal.Column('currency', sqlal.String(3), nullable=True), 
         sqlal.Column('market_data_source', sqlal.String(20), nullable=True), 
         sqlal.Column('trading_location', sqlal.String(20), nullable=True), 
         sqlal.Column('country', sqlal.String(20), nullable=True), 
         sqlal.Column('sector', sqlal.String(80), nullable=True) 
         ) 

market_price_data = sqlal.Table('market_price_data', metadata, 
           sqlal.Column('Date', sqlal.DateTime, nullable=True), 
           sqlal.Column('ticker', sqlal.String(10), sqlal.ForeignKey('product.ticker'), nullable=True), 
           sqlal.Column('adj_close', sqlal.Float, nullable=True), 
           sqlal.Column('log_return', sqlal.Float, nullable=True) 
           ) 

metadata.create_all(mysql_engine) 

GetTimeSeriesLevels = pd.read_sql_query('SELECT Date, ticker, adj_close FROM market_price_data Order BY ticker ASC', mysql_engine) 
GetTimeSeriesLevels['log_return'] = np.log(GetTimeSeriesLevels.groupby('ticker')['adj_close'].apply(lambda x: x.div(x.shift(1)))).dropna() 
GetTimeSeriesLevels['log_return'].fillna('NULL', inplace=True) 
insert_yahoo_data = market_price_data.insert().values(GetTimeSeriesLevels [['log_return']].to_dict('records')) 
mysql_engine.execute(insert_yahoo_data) 

データベースの外観は次のとおりです。

Date    ticker adj_close log_return 
2016-11-21 00:00:00 AAPL 111.73 NULL 
2016-11-22 00:00:00 AAPL 111.8  NULL 
2016-11-23 00:00:00 AAPL 111.23 NULL  
2016-11-25 00:00:00 AAPL 111.79 NULL 
2016-11-28 00:00:00 AAPL 111.57 NULL 
2016-11-23 00:00:00 ACN  119.82 NULL 
2016-11-25 00:00:00 ACN  120.74 NULL 
2016-11-28 00:00:00 ACN  120.76 NULL 
2016-11-29 00:00:00 ACN  120.94 NULL 
2016-11-30 00:00:00 ACN  119.43 NULL 
... 

それは次のようになります。

Date    ticker adj_close log_return 
2016-11-21 00:00:00 AAPL 111.73 NULL 
2016-11-22 00:00:00 AAPL 111.8  0.000626 
2016-11-23 00:00:00 AAPL 111.23 -0.005111 
2016-11-25 00:00:00 AAPL 111.79 0.005022 
2016-11-28 00:00:00 AAPL 111.57 -0.001970 
2016-11-21 00:00:00 ACN  119,68 NULL 
2016-11-22 00:00:00 ACN  119,48 -0,001672521 
23.11.2016 00:00:00 ACN  119,82 0,002841623 
2016-11-25 00:00:00 ACN  120,74 0,007648857 
2016-11-28 00:00:00 ACN  120,76 0,000165631  
... 
+0

@Parfait、答えてくれてありがとう:

以下

CREATE AS ...で一時テーブルにダンプまたはネストSELECT文で複雑なUPDATEクエリに変換することができますselect文です。上記のコードにsqlalchemyのインポートを追加しました。 – MCM

答えて

1

恥、私は、最終的なテーブルとそれに参加する一時テーブルにパンダのデータフレームを投棄を検討し、唯一、生のSQL SQLAlchemyの知らない間:

# DUMP TO TEMP TABLE (REPLACING EACH TIME) 
GetTimeSeriesLevels.to_sql(name='log_return_temp', con=mysql_engine, if_exists='replace', 
          index=False) 

# SQL UPDATE (USING TRANSACTION) 
with engine.begin() as conn:  
    conn.execute("UPDATE market_price_data f" + 
       " INNER JOIN log_return_temp t" + 
       " ON f.Date = t.Date" + 
       " AND f.ticker = t.ticker" + 
       " SET f.log_return = t.log_return;") 

engine.dispose() 

また、MySQLで直接ログ変換を行うことを検討してください。私が見ているものから、パンダ/ナンバーコードでは、現在行のadj_closeの商を最終行のadj_closeで変換します。 MySQLは、現在の行と最後の行を整列するために自己結合を実行できます。 MySQLは自然なログを維持します。mathematical operators

SELECT t1.*, LOG(t1.adj_close/t2.adj_close) As log_return 
FROM  
    (SELECT m.Date, m.ticker, m.adj_close, 
      (SELECT Count(*) FROM market_price_data sub 
      WHERE sub.Date <= m.Date AND sub.ticker = m.ticker) AS rank 
    FROM market_price_data m) As t1 

INNER JOIN 
    (SELECT m.Date, m.ticker, m.adj_close, 
      (SELECT Count(*) FROM market_price_data sub 
      WHERE sub.Date <= m.Date AND sub.ticker = m.ticker) AS rank 
    FROM market_price_data m) As t1 

ON t1.rank = (t2.rank - 1) AND t1.ticker = t2.ticker AND t1.Date = t2.Date 
+0

何とか同じエラーメッセージが表示されます:**(mysql.connector.errors.DatabaseError)1265(01000):行1の 'log_return'列のデータが切り捨てられました[SQL:** – MCM

+0

'log_return'データ型ですか?または、小数はいくつですか? Pythonの図形を丸めます。 – Parfait

+0

私はfinnnaで0の代わりにNaNのために定義されたNULLを使用していますので、今はうまくいきます。ありがとう。 – MCM

関連する問題