PythonでAWS-RDSのMySQLをテスト(Appleの株価プロット)
PythonでAWS-RDSのMySQLをテスト(Appleの株価プロット):
ちょっとしたアプリを作りたくRDSを勉強中
既存のCSVファイル(今回は株価)から時系列データと株価を抽出し、RDS-MySQLに入れ、そこから更に参照し、webでグラフプロットしたい、今回はその前段階で単に上げたデータをまたローカルに戻すという作業のメモ。
必要なもの
250日の移動平均線もありますが、今回は値動きのみにします。
ちゃんと格納されているか確認します。
格納されていましたね。
さて、これをちまちま手順を踏んでDataFrameの中に入れることもできますが、もっと便利な方法があります。
ダイレクトにSQLからdf形式に変換してくれる便利なモジュールです。
Matplotlibでエラーが出てしまいました。
そうか、インデックスをdatetimeにし忘れたのかと思ったら
x軸がid、y軸が年代になってしまいました。
datetime列のキャストを忘れていたんですね。Javaだと型は常に意識していたのですが、Pythonですっかり忘れていました。そしてdatiteimeを
きれいに再プロットすることができました!
アップするときに、下記のようにPandasのイテレータで回しながら入れていこうとしたが、キャストしてもうまくいかなかった
苦渋の選択として辞書化させリストに戻しました。
うまい方法があれば教えていただきたいです。
他のやり方として
ちょっとしたアプリを作りたくRDSを勉強中
趣旨を簡単に説明
既存のCSVファイル(今回は株価)から時系列データと株価を抽出し、RDS-MySQLに入れ、そこから更に参照し、webでグラフプロットしたい、今回はその前段階で単に上げたデータをまたローカルに戻すという作業のメモ。必要なもの
- 株価と時系列を対照させたデータ
- AWSアカウント
- Python
PythonでCSVデータの送信準備
stocks = pd.read_csv('stock_px_2.csv', parse_dates=True, index_col=0) # Appleの株価のみ参照 aapl_stock = stocks[['AAPL']] # 営業日ごとに欠損値を前参照 aapl_stock = aapl_stock.resample('B').ffill() aapl_stock.plot()
ffill
でデータ欠損がある場合に埋めます。250日の移動平均線もありますが、今回は値動きのみにします。
AWSにログイン&UP
rds = 'xxxxxxxxxxxxxxxx' con = mysql.connector.connect( host=rds, user="xxxx", password="xxxxxxxx", database='xxxxxxxx' ) # 例外処理 try: cur = con.cursor() with open('stock_px_mini.csv') as f: reader = csv.reader(f) heder = next(reader, None) cur.execute("DROP TABLE IF EXISTS `stock_table_csv`") cur.execute("""CREATE TABLE IF NOT EXISTS `stock_table_csv`( `_id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, `datetime` DATETIME, `value` FLOAT);""") con.commit() sql = "INSERT INTO `stock_table_csv` (datetime, value) VALUES (%s, %s);" for i in reader: cur.execute(sql, (i[0], i[1])) con.commit() except mysql.connector.Error as e: print("Error code:", e.errno) # error number print("SQLSTATE value:", e.sqlstate) # SQLSTATE value print("Error message:", e.msg) # error message print("Error:", e) # errno, sqlstate, msg values s = str(e) print("Error:", s) #Pandasでも辞書リストを経由してできました。 sql = "INSERT INTO stock_table (datetime, value) VALUES (%s, %s);" for i in list(df.AAPL.to_dict().items()): cur.execute(sql, i) con.commit()
cursor = con.cursor() sql ='SELECT * FROM stock_table_csv1' cursor.execute(sql) rows = cursor.fetchall() for i in rows: print(i) ''' (1, datetime.datetime(2003, 1, 2, 0, 0), 7.4) (2, datetime.datetime(2003, 1, 3, 0, 0), 7.45) (3, datetime.datetime(2003, 1, 6, 0, 0), 7.45) (4, datetime.datetime(2003, 1, 7, 0, 0), 7.43) (5, datetime.datetime(2003, 1, 8, 0, 0), 7.28) (6, datetime.datetime(2003, 1, 9, 0, 0), 7.34) (7, datetime.datetime(2003, 1, 10, 0, 0), 7.36) (8, datetime.datetime(2003, 1, 13, 0, 0), 7.32) (9, datetime.datetime(2003, 1, 14, 0, 0), 7.3) (10, datetime.datetime(2003, 1, 15, 0, 0), 7.22) (11, datetime.datetime(2003, 1, 16, 0, 0), 7.31) (12, datetime.datetime(2003, 1, 17, 0, 0), 7.05) '''
さて、これをちまちま手順を踏んでDataFrameの中に入れることもできますが、もっと便利な方法があります。
topandas
import pandas.io.sql as pdsql df = pdsql.read_sql(sql, con, index_col='_id') print(df) ''' datetime value _id 1 2003-01-02 7.40 2 2003-01-03 7.45 3 2003-01-06 7.45 4 2003-01-07 7.43 5 2003-01-08 7.28 6 2003-01-09 7.34 7 2003-01-10 7.36 8 2003-01-13 7.32 9 2003-01-14 7.30 10 2003-01-15 7.22 11 2003-01-16 7.31 12 2003-01-17 7.05 13 2003-01-21 7.01 14 2003-01-22 6.94 15 2003-01-23 7.09 16 2003-01-24 6.90 17 2003-01-27 7.07 18 2003-01-28 7.29 19 2003-01-29 7.47 '''
index_col=
でインデックスも指定できます。
MySQLから取得したデータをプロット
forplot
df.plot() ''' ValueError: view limit minimum -36714.312 is less than 1 and is an invalid Matplotlib date value. This often happens if you pass a non-datetime value to an axis that has datetime units '''
そうか、インデックスをdatetimeにし忘れたのかと思ったら
df.set_index('datetime', inplace=True)
x軸がid、y軸が年代になってしまいました。
datetime列のキャストを忘れていたんですね。Javaだと型は常に意識していたのですが、Pythonですっかり忘れていました。そしてdatiteimeを
set_index
でインデキシングします。# 下記だとSeriesで返されるのでNG # df = pd.to_datetime(df['datetime']) df['datetime'] = pd.to_datetime(df['datetime']) df.set_index('datetime', inplace=True)
きれいに再プロットすることができました!
詰まったこと
アップするときに、下記のようにPandasのイテレータで回しながら入れていこうとしたが、キャストしてもうまくいかなかったfor column_name, item in df.AAPL.iteritems(): cur.execute(str(column_name), item) con.commit()
うまい方法があれば教えていただきたいです。
他のやり方として
sqlalchemy
で.to_sql
すれば簡単にアップすことができるのですが、今回はforで回したかったので見送りました。python3は辞書の順番も保持してくれるので今回省略したのですが、本当はちゃんとforで回して順番通りにリストに格納しないといけませんね。
コメント
コメントを投稿