Act 06. Pythonでデータ処理を行う
はじめに
Act 01. AIで外国為替を自動売買するまでの道のりをベースに学習を進めて行く。
Pythonを用いて機械学習を行う場合、データの前処理が必要らしい。
Pythonではデータ処理を行うための様々なライブラリが提供されている。
結構なボリュームになりそうだが挫けずに勉強しようと思う。
そもそも何を勉強すれば良いか分からないため、ChatGPTさんに質問してみた。
どうやら為替などの時系列データを扱う場合は以下を学んだ方がよいらしい。
以下、ChatGPTさんの回答
-
Pandas
時系列データの前処理において最も一般的なライブラリです。データのクリーニング、欠損値の処理、リサンプリング、データの結合やフィルタリングなど、多くの機能を提供しています。 -
NumPy
数値計算を効率的に行うための基盤ライブラリで、配列操作や数学的な計算が必要な場合に役立ちます。Pandasと組み合わせて使うことが多いです。 -
Feature-engine
特徴量エンジニアリングに特化したライブラリです。データの変換やエンコーディング、スケーリング、フィルタリングなど、機械学習の準備をスムーズに行うことができます。 -
Scikit-learn
データ前処理のためのツールも豊富です。データのスケーリング、エンコーディング、特徴選択、交差検証など、機械学習のためのデータ準備が行えます。 -
Dask
大規模データを扱う場合、Pandasに似たAPIを持ちながら並列処理をサポートしているため、メモリに収まらないデータの前処理に役立ちます。 -
Category Encoders
カテゴリカルデータのエンコーディングに特化したライブラリで、様々なエンコーディング手法を提供しています。これにより、モデルへの入力データを整形する際に便利です。
まとめ
データの前処理には、PandasとNumPyが基本ですが、特定のニーズに応じてFeature-engineやScikit-learn、Daskを組み合わせて使うと、より効率的にデータを整形できます。データの性質に応じて最適なツールを選ぶと良いでしょう。
なるほど、全くわからないがとりあえず基本と言われているNumPy
とPandas
を学ぼうかな。
それ以外のライブラリについては必要に応じて学ぼうと思う。
ここでは時系列データの学習に使える便利なライブラリが、後4つは存在しているということだけ覚えておく。未来の自分が躓いた時に勉強してくれるだろう。
NumPy
まずはNumPyから。
と思ったけど、NumPyは数学を学んでからの方がいい気がしてきた。
NumPyはPythonで数値計算を行うためのライブラリらしい。
N次元配列や算術演算や三角関数、指数関数、対数関数、線形代数など。。
しっかりと理解しながら進めて行きたいからここでは一旦スキップ。
NumPyが見たくてこの記事にたどり着いた人には大変申し訳ない。
けどこのシリーズの記事は自分の日記や備忘録のために載せてるんだ。。
「数学の知識がない状態でNumPyに手を出すのはやめた方がいい」という考えになったことをここに残しておく。
Act01で立てた予定通りにはいかないもんだね。面白い
Pandas
Pandasは、Pythonでデータ操作や分析を行うための強力なライブラリらしい。
少し調べてみたが、表とかを操作するようなイメージだった。
こっちは数学とかあまり関係なさそうだからこのタイミングで学習を進めようと思う。
まずは実際に使うとしたらどういう感じになるかイメージしてみる。
ぱっと思いついたのは以下。
- APIで為替のJSONデータを上手く使う(よくわかっていないので曖昧な表現)
- 取得したデータから新たなデータを計算して追加したい(移動平均線を計算するイメージ)
- MAX、MIN、AVEを取得したい
- 時間指定でデータを取得したい
とりあえずこんな内容で学習を進めて行く。
やっている途中で気づいたことがあったら追記するかも。
【追記】
思いついたことを全部試している。かなり長い記事になってるから心して読んでね。
JSONの読み込みと変換
ChatGPTさんに頼んで以下のデータを作ってもらった。
これは1時間分の5分足データで、日時 / 始値 / 高値 / 安値 / 終値 / ボリュームのデータが存在する。
[
{"timestamp": "2024-10-25T10:00:00Z", "open": 1.1000, "high": 1.1020, "low": 1.0990, "close": 1.1010, "volume": 1000},
{"timestamp": "2024-10-25T10:05:00Z", "open": 1.1010, "high": 1.1030, "low": 1.1000, "close": 1.1025, "volume": 1100},
{"timestamp": "2024-10-25T10:10:00Z", "open": 1.1025, "high": 1.1040, "low": 1.1015, "close": 1.1035, "volume": 1050},
{"timestamp": "2024-10-25T10:15:00Z", "open": 1.1035, "high": 1.1050, "low": 1.1025, "close": 1.1045, "volume": 950},
{"timestamp": "2024-10-25T10:20:00Z", "open": 1.1045, "high": 1.1060, "low": 1.1035, "close": 1.1055, "volume": 980},
{"timestamp": "2024-10-25T10:25:00Z", "open": 1.1055, "high": 1.1070, "low": 1.1045, "close": 1.1065, "volume": 1000},
{"timestamp": "2024-10-25T10:30:00Z", "open": 1.1065, "high": 1.1080, "low": 1.1055, "close": 1.1075, "volume": 1200},
{"timestamp": "2024-10-25T10:35:00Z", "open": 1.1075, "high": 1.1090, "low": 1.1065, "close": 1.1085, "volume": 1150},
{"timestamp": "2024-10-25T10:40:00Z", "open": 1.1085, "high": 1.1100, "low": 1.1075, "close": 1.1095, "volume": 1100},
{"timestamp": "2024-10-25T10:45:00Z", "open": 1.1095, "high": 1.1110, "low": 1.1085, "close": 1.1100, "volume": 1050},
{"timestamp": "2024-10-25T10:50:00Z", "open": 1.1100, "high": 1.1120, "low": 1.1090, "close": 1.1110, "volume": 1200},
{"timestamp": "2024-10-25T10:55:00Z", "open": 1.1110, "high": 1.1130, "low": 1.1100, "close": 1.1120, "volume": 1250}
]
まずはJSONファイルを読み込む方法を調べた。
PandasでJSONファイルを読み込む方法もあるっぽいけど、実際はそんな使い方をしない。
恐らくだが、requestsライブラリを使いAPIを呼び出して為替データを取得すると思う。
つまり、一度に一つの時間のデータ(X時Y分Z秒)しか取得することが出来ない。
ということで、今回はJSONファイルを1行ずつ読み込み、順に処理を行うようにしてみようと思う。
まずはファイルを読み込まないと話にならない。
import json
with open("5min_data.json") as f:
data = json.load(f)
print(data)
これでうまく読み込めた。
実行すると以下の出力。どうやら全行読み込んでしまった。
[{'timestamp': '2024-10-25T10:00:00Z', 'open': 1.1, 'high': 1.102, 'low': 1.099, 'close': 1.101, 'volume': 1000}, {'timestamp': '2024-10-25T10:05:00Z', 'open': 1.101, 'high': 1.103, 'low': 1.1, 'close': 1.1025, 'volume': 1100}, {'timestamp': '2024-10-25T10:10:00Z', 'open': 1.1025, 'high': 1.104, 'low': 1.1015, 'close': 1.1035, 'volume': 1050}, {'timestamp': '2024-10-25T10:15:00Z', 'open': 1.1035, 'high': 1.105, 'low': 1.1025, 'close': 1.1045, 'volume': 950}, {'timestamp': '2024-10-25T10:20:00Z', 'open': 1.1045, 'high': 1.106, 'low': 1.1035, 'close': 1.1055, 'volume': 980}, {'timestamp': '2024-10-25T10:25:00Z', 'open': 1.1055, 'high': 1.107, 'low': 1.1045, 'close': 1.1065, 'volume': 1000}, {'timestamp': '2024-10-25T10:30:00Z', 'open': 1.1065, 'high': 1.108, 'low': 1.1055, 'close': 1.1075, 'volume': 1200}, {'timestamp': '2024-10-25T10:35:00Z', 'open': 1.1075, 'high': 1.109, 'low': 1.1065, 'close': 1.1085, 'volume': 1150}, {'timestamp': '2024-10-25T10:40:00Z', 'open': 1.1085, 'high': 1.11, 'low': 1.1075, 'close': 1.1095, 'volume': 1100}, {'timestamp': '2024-10-25T10:45:00Z', 'open': 1.1095, 'high': 1.111, 'low': 1.1085, 'close': 1.11, 'volume': 1050}, {'timestamp': '2024-10-25T10:50:00Z', 'open': 1.11, 'high': 1.112, 'low': 1.109, 'close': 1.111, 'volume': 1200}, {'timestamp': '2024-10-25T10:55:00Z', 'open': 1.111, 'high': 1.113, 'low': 1.11, 'close': 1.112, 'volume': 1250}]
以下に修正してみた。
import json
with open("5min_data.json") as f:
data = json.load(f)
for item in data:
print(item)
print("="*60)
実行結果は以下。どうやら1行ずつ読み込んでいる。いいね
{'timestamp': '2024-10-25T10:00:00Z', 'open': 1.1, 'high': 1.102, 'low': 1.099, 'close': 1.101, 'volume': 1000}
============================================================
{'timestamp': '2024-10-25T10:05:00Z', 'open': 1.101, 'high': 1.103, 'low': 1.1, 'close': 1.1025, 'volume': 1100}
============================================================
{'timestamp': '2024-10-25T10:10:00Z', 'open': 1.1025, 'high': 1.104, 'low': 1.1015, 'close': 1.1035, 'volume': 1050}
============================================================
{'timestamp': '2024-10-25T10:15:00Z', 'open': 1.1035, 'high': 1.105, 'low': 1.1025, 'close': 1.1045, 'volume': 950}
============================================================
{'timestamp': '2024-10-25T10:20:00Z', 'open': 1.1045, 'high': 1.106, 'low': 1.1035, 'close': 1.1055, 'volume': 980}
============================================================
{'timestamp': '2024-10-25T10:25:00Z', 'open': 1.1055, 'high': 1.107, 'low': 1.1045, 'close': 1.1065, 'volume': 1000}
============================================================
{'timestamp': '2024-10-25T10:30:00Z', 'open': 1.1065, 'high': 1.108, 'low': 1.1055, 'close': 1.1075, 'volume': 1200}
============================================================
{'timestamp': '2024-10-25T10:35:00Z', 'open': 1.1075, 'high': 1.109, 'low': 1.1065, 'close': 1.1085, 'volume': 1150}
============================================================
{'timestamp': '2024-10-25T10:40:00Z', 'open': 1.1085, 'high': 1.11, 'low': 1.1075, 'close': 1.1095, 'volume': 1100}
============================================================
{'timestamp': '2024-10-25T10:45:00Z', 'open': 1.1095, 'high': 1.111, 'low': 1.1085, 'close': 1.11, 'volume': 1050}
============================================================
{'timestamp': '2024-10-25T10:50:00Z', 'open': 1.11, 'high': 1.112, 'low': 1.109, 'close': 1.111, 'volume': 1200}
============================================================
{'timestamp': '2024-10-25T10:55:00Z', 'open': 1.111, 'high': 1.113, 'low': 1.11, 'close': 1.112, 'volume': 1250}
============================================================
次にPandasで操作できる形式に変換しようと思う。
一旦データを一つだけ使ってPandasを試してみる。
ここで一つ注意するのは、PandasのDataFrameクラスに渡す引数は配列にするということ。
import json
import pandas as pd
with open("5min_data.json") as f:
data = json.load(f)
pd = pd.DataFrame([data[0]]) ### 配列にする
print(pd)
# for item in data:
# print(item)
# print("="*60)
出力は以下の通り。
すご!インデックスにカラムまでついていい感じになってる。
timestamp open high low close volume
0 2024-10-25T10:00:00Z 1.1 1.102 1.099 1.101 1000
JSONファイルの内容を順に取得してみた。
import json
import pandas as pd
json_data_list = []
with open("5min_data.json") as f:
data = json.load(f)
for item in data:
json_data_list.append(item)
df = pd.DataFrame(json_data_list)
print(df)
出力は以下の通り。
なんだかいい感じ。
timestamp open high low close volume
0 2024-10-25T10:00:00Z 1.1000 1.102 1.0990 1.1010 1000
1 2024-10-25T10:05:00Z 1.1010 1.103 1.1000 1.1025 1100
2 2024-10-25T10:10:00Z 1.1025 1.104 1.1015 1.1035 1050
3 2024-10-25T10:15:00Z 1.1035 1.105 1.1025 1.1045 950
4 2024-10-25T10:20:00Z 1.1045 1.106 1.1035 1.1055 980
5 2024-10-25T10:25:00Z 1.1055 1.107 1.1045 1.1065 1000
6 2024-10-25T10:30:00Z 1.1065 1.108 1.1055 1.1075 1200
7 2024-10-25T10:35:00Z 1.1075 1.109 1.1065 1.1085 1150
8 2024-10-25T10:40:00Z 1.1085 1.110 1.1075 1.1095 1100
9 2024-10-25T10:45:00Z 1.1095 1.111 1.1085 1.1100 1050
10 2024-10-25T10:50:00Z 1.1100 1.112 1.1090 1.1110 1200
11 2024-10-25T10:55:00Z 1.1110 1.113 1.1100 1.1120 1250
ここまで来てふと思った。
実際に使うときって、10:00~10:55までのデータは事前に持っていて、
11:00のデータをAPIで取得するはずじゃん。と、、
ということでコードを書き換えた。(思ったこと、気づいたことを記事にしてるから許して。)
これで10:00~10:55までのデータと11:00のデータがそろった。
import pandas as pd
# 事前に蓄えていたデータ
df = pd.read_json('5min_data.json')
# APIで取得するはずのデータ
next_data = {"timestamp": "2024-10-25 11:00:00+00:00", "open": 1.1120, "high": 1.1140, "low": 1.1110, "close": 1.1130, "volume": 1300}
行を末尾に追加する場合はappend
メソッドを使用するらしい。
Pandasのappendメソッドは非推奨になっており、代わりにconcat
を使うらしい。
concat
はDataFrame同士を結合するメソッド。普段使うのはこれになりそう。
import pandas as pd
# 事前に蓄えていたデータ
df = pd.read_json('5min_data.json')
# APIで取得するはずのデータ
next_data = {"timestamp": "2024-10-25 11:00:00+00:00", "open": 1.1120, "high": 1.1140, "low": 1.1110, "close": 1.1130, "volume": 1300}
next_df = pd.DataFrame([next_data])
### `[df, next_df]`で結合したいDataFrameを複数指定
### `ignore_index=True`は、インデックスをいい感じに調整してもらう
df = pd.concat([df, next_df], ignore_index=True)
print(df)
出力は以下の通り。
timestamp open high low close volume
0 2024-10-25 10:00:00+00:00 1.1000 1.102 1.0990 1.1010 1000
1 2024-10-25 10:05:00+00:00 1.1010 1.103 1.1000 1.1025 1100
2 2024-10-25 10:10:00+00:00 1.1025 1.104 1.1015 1.1035 1050
3 2024-10-25 10:15:00+00:00 1.1035 1.105 1.1025 1.1045 950
4 2024-10-25 10:20:00+00:00 1.1045 1.106 1.1035 1.1055 980
5 2024-10-25 10:25:00+00:00 1.1055 1.107 1.1045 1.1065 1000
6 2024-10-25 10:30:00+00:00 1.1065 1.108 1.1055 1.1075 1200
7 2024-10-25 10:35:00+00:00 1.1075 1.109 1.1065 1.1085 1150
8 2024-10-25 10:40:00+00:00 1.1085 1.110 1.1075 1.1095 1100
9 2024-10-25 10:45:00+00:00 1.1095 1.111 1.1085 1.1100 1050
10 2024-10-25 10:50:00+00:00 1.1100 1.112 1.1090 1.1110 1200
11 2024-10-25 10:55:00+00:00 1.1110 1.113 1.1100 1.1120 1250
12 2024-10-25 11:00:00+00:00 1.1120 1.114 1.1110 1.1130 1300
やっと一つ目のことが確認できた。
既存のデータをもとに新しい列を追加する
次にやりたいことは、データの内容を元に新しいデータを作成したい。
今回やってみるのは以下の2つ。
- onen, high, low, closeの平均を算出して、averageという列にデータを追加する
- 一つ前のvolumeとの差分を計算して、diff_volumeという列にデータを追加する
文章だとイメージがわかないかもだから早速1つ目を試してみる。
1. 平均を算出してaverageという列にデータを追加する
早速やっていくわけだが、まず最初に考えたのが特定のカラムのデータを取得する方法。
例えばopen
の列のデータを取得したい。その場合は以下の記述で行けた。
df.open
これってもしかして、open
とclose
とかを足すことが出来るのでは・・・?
という甘い期待を抱いてこんなコードを書いてみた。
open = df.open
close = df.close
high = df.high
low = df.low
print((open + close + high + low) / 4)
出力は以下の通り。なんかいけちゃった
0 1.100500
1 1.101625
2 1.102875
3 1.103875
4 1.104875
5 1.105875
6 1.106875
7 1.107875
8 1.108875
9 1.109750
10 1.110500
11 1.111500
12 1.112500
dtype: float64
そして最終的なコードはこう!
import pandas as pd
# 事前に蓄えていたデータ
df = pd.read_json('5min_data.json')
# APIで取得するはずのデータ
next_data = {"timestamp": "2024-10-25 11:00:00+00:00", "open": 1.1120, "high": 1.1140, "low": 1.1110, "close": 1.1130, "volume": 1300}
next_df = pd.DataFrame([next_data])
df = pd.concat([df, next_df], ignore_index=True)
open = df.open
close = df.close
high = df.high
low = df.low
average = (open + close + high + low) / 4 ### 平均値を取得
### DataFrameのassignメソッドで列を追加する。
### 列名=データの形式で引数を渡す。
df = df.assign(average=average)
print(df)
出力は以下の通り。なんかいい感じ。
timestamp open high low close volume average
0 2024-10-25 10:00:00+00:00 1.1000 1.102 1.0990 1.1010 1000 1.100500
1 2024-10-25 10:05:00+00:00 1.1010 1.103 1.1000 1.1025 1100 1.101625
2 2024-10-25 10:10:00+00:00 1.1025 1.104 1.1015 1.1035 1050 1.102875
3 2024-10-25 10:15:00+00:00 1.1035 1.105 1.1025 1.1045 950 1.103875
4 2024-10-25 10:20:00+00:00 1.1045 1.106 1.1035 1.1055 980 1.104875
5 2024-10-25 10:25:00+00:00 1.1055 1.107 1.1045 1.1065 1000 1.105875
6 2024-10-25 10:30:00+00:00 1.1065 1.108 1.1055 1.1075 1200 1.106875
7 2024-10-25 10:35:00+00:00 1.1075 1.109 1.1065 1.1085 1150 1.107875
8 2024-10-25 10:40:00+00:00 1.1085 1.110 1.1075 1.1095 1100 1.108875
9 2024-10-25 10:45:00+00:00 1.1095 1.111 1.1085 1.1100 1050 1.109750
10 2024-10-25 10:50:00+00:00 1.1100 1.112 1.1090 1.1110 1200 1.110500
11 2024-10-25 10:55:00+00:00 1.1110 1.113 1.1100 1.1120 1250 1.111500
12 2024-10-25 11:00:00+00:00 1.1120 1.114 1.1110 1.1130 1300 1.112500
これでいいや。と思ったかもしれないが、もっといい方法があると思うのでChatGPTさんに質問。
回答をもとにコードを変更してみた。
このコードでも同様の結果を得ることに成功。まあ、やってることは同じだしそりゃそうだ。
assign
を使わないでも列を追加できることが分かったからよしとする。
import pandas as pd
# 事前に蓄えていたデータ
df = pd.read_json('5min_data.json')
# APIで取得するはずのデータ
next_data = {"timestamp": "2024-10-25 11:00:00+00:00", "open": 1.1120, "high": 1.1140, "low": 1.1110, "close": 1.1130, "volume": 1300}
next_df = pd.DataFrame([next_data])
df = pd.concat([df, next_df], ignore_index=True)
df['average'] = (df['open'] + df['close'] + df['high'] + df.get('low', 0)) / 4 # lowが存在しない場合は0として扱うことも可能
print(df)
もっと画期的な方法を教えてくれ!と懇願した結果、mean
メソッドを教えてくれた。
import pandas as pd
# 事前に蓄えていたデータ
df = pd.read_json('5min_data.json')
# APIで取得するはずのデータ
next_data = {"timestamp": "2024-10-25 11:00:00+00:00", "open": 1.1120, "high": 1.1140, "low": 1.1110, "close": 1.1130, "volume": 1300}
next_df = pd.DataFrame([next_data])
df = pd.concat([df, next_df], ignore_index=True)
# DataFrameには`sum`や`mean`、`min`など様々なメソッドを提供しているため、列や行に対する処理を迅速に行うことが出来る
# `axis=1`というのは行を対象にしている。
df["average"] = df[["open", "close", "high", "low"]].mean(axis=1)
print(df)
ちなみに、axis=0
にした場合は列が対象になるらしい。
それと、df[["open", "close", "high", "low"]]
は、
df["open"]
、df["close"]
・・・と同じ意味で、それぞれのカラムを一気に参照出来るっポイ。
最初に比べるときれいなコードになったし、きっとこれが正解だろう。
2. 一つ前との差分を計算してdiff_volumeという列にデータを追加する
ということで次に進もうと思う。
これは何かというと、11:00のdiff_volumeの値は、10:55と11:00のvolumeデータの差分を設定したい。
直ぐに調べる前に色々試してみる。
まずはこれ。indexが0のvolumeデータを取得できた。狙い通り。
df.volume[0]
# 出力:1000
一つ思いついたのは、
volumeデータを列ごと取得して一行ずらす。
その後に差分を求めれば行けるのでは?ってこと。試してみたけど断念。
volume = df.volume
volume = volume.drop(axis=0, index=volume.count() - 1)
print(volume)
出力は以下の通り。
末尾を消すことは出来たが、最初の一行目に追加する方法がよくわからなかった。
悔しいが何かいい方法がないか調べてみる。
0 1000
1 1100
2 1050
3 950
4 980
5 1000
6 1200
7 1150
8 1100
9 1050
10 1200
11 1250
Name: volume, dtype: int64
調べてらめっちゃ簡単だった。。
diff
メソッドを使用すると簡単にデータの差分を取得できる。
知ってるのと知らないのだと天と地の差だね。
import pandas as pd
# 事前に蓄えていたデータ
df = pd.read_json('5min_data.json')
# APIで取得するはずのデータ
next_data = {"timestamp": "2024-10-25 11:00:00+00:00", "open": 1.1120, "high": 1.1140, "low": 1.1110, "close": 1.1130, "volume": 1300}
next_df = pd.DataFrame([next_data])
df = pd.concat([df, next_df], ignore_index=True)
df["average"] = df[["open", "close", "high", "low"]].min(axis=1)
df["diff_volume"] = df["volume"].diff()
print(df)
出力は以下の通り。
diff
メソッドは引数に期間を指定することで、何個前との差分を取るかを指定できるらしい。
timestamp open high low close volume average diff_volume
0 2024-10-25 10:00:00+00:00 1.1000 1.102 1.0990 1.1010 1000 1.0990 NaN
1 2024-10-25 10:05:00+00:00 1.1010 1.103 1.1000 1.1025 1100 1.1000 100.0
2 2024-10-25 10:10:00+00:00 1.1025 1.104 1.1015 1.1035 1050 1.1015 -50.0
3 2024-10-25 10:15:00+00:00 1.1035 1.105 1.1025 1.1045 950 1.1025 -100.0
4 2024-10-25 10:20:00+00:00 1.1045 1.106 1.1035 1.1055 980 1.1035 30.0
5 2024-10-25 10:25:00+00:00 1.1055 1.107 1.1045 1.1065 1000 1.1045 20.0
6 2024-10-25 10:30:00+00:00 1.1065 1.108 1.1055 1.1075 1200 1.1055 200.0
7 2024-10-25 10:35:00+00:00 1.1075 1.109 1.1065 1.1085 1150 1.1065 -50.0
8 2024-10-25 10:40:00+00:00 1.1085 1.110 1.1075 1.1095 1100 1.1075 -50.0
9 2024-10-25 10:45:00+00:00 1.1095 1.111 1.1085 1.1100 1050 1.1085 -50.0
10 2024-10-25 10:50:00+00:00 1.1100 1.112 1.1090 1.1110 1200 1.1090 150.0
11 2024-10-25 10:55:00+00:00 1.1110 1.113 1.1100 1.1120 1250 1.1100 50.0
12 2024-10-25 11:00:00+00:00 1.1120 1.114 1.1110 1.1130 1300 1.1110 50.0
追加
指定した期間の平均値を求めることはできるのか?と気になって調べてみた。
結論、rolling
メソッドを使用すればOKらしい。
import pandas as pd
# 事前に蓄えていたデータ
df = pd.read_json('5min_data.json')
# APIで取得するはずのデータ
next_data = {"timestamp": "2024-10-25 11:00:00+00:00", "open": 1.1120, "high": 1.1140, "low": 1.1110, "close": 1.1130, "volume": 1300}
next_df = pd.DataFrame([next_data])
df = pd.concat([df, next_df], ignore_index=True)
df["average"] = df[["open", "close", "high", "low"]].min(axis=1)
df["diff_volume"] = df["volume"].diff()
# windowで期間を取得し、その期間の平均を算出する
df["mean_open"] = df["open"].rolling(window=3).mean()
print(df)
出力は以下の通り。
timestamp open high low close volume average diff_volume mean_open
0 2024-10-25 10:00:00+00:00 1.1000 1.102 1.0990 1.1010 1000 1.0990 NaN NaN
1 2024-10-25 10:05:00+00:00 1.1010 1.103 1.1000 1.1025 1100 1.1000 100.0 NaN
2 2024-10-25 10:10:00+00:00 1.1025 1.104 1.1015 1.1035 1050 1.1015 -50.0 1.101167
3 2024-10-25 10:15:00+00:00 1.1035 1.105 1.1025 1.1045 950 1.1025 -100.0 1.102333
4 2024-10-25 10:20:00+00:00 1.1045 1.106 1.1035 1.1055 980 1.1035 30.0 1.103500
5 2024-10-25 10:25:00+00:00 1.1055 1.107 1.1045 1.1065 1000 1.1045 20.0 1.104500
6 2024-10-25 10:30:00+00:00 1.1065 1.108 1.1055 1.1075 1200 1.1055 200.0 1.105500
7 2024-10-25 10:35:00+00:00 1.1075 1.109 1.1065 1.1085 1150 1.1065 -50.0 1.106500
8 2024-10-25 10:40:00+00:00 1.1085 1.110 1.1075 1.1095 1100 1.1075 -50.0 1.107500
9 2024-10-25 10:45:00+00:00 1.1095 1.111 1.1085 1.1100 1050 1.1085 -50.0 1.108500
10 2024-10-25 10:50:00+00:00 1.1100 1.112 1.1090 1.1110 1200 1.1090 150.0 1.109333
11 2024-10-25 10:55:00+00:00 1.1110 1.113 1.1100 1.1120 1250 1.1100 50.0 1.110167
12 2024-10-25 11:00:00+00:00 1.1120 1.114 1.1110 1.1130 1300 1.1110 50.0 1.111000
MAX、MIN、AVEを取得
こんなのもう余裕でしょ!
import pandas as pd
# 事前に蓄えていたデータ
df = pd.read_json('5min_data.json')
# APIで取得するはずのデータ
next_data = {"timestamp": "2024-10-25 11:00:00+00:00", "open": 1.1120, "high": 1.1140, "low": 1.1110, "close": 1.1130, "volume": 1300}
next_df = pd.DataFrame([next_data])
df = pd.concat([df, next_df], ignore_index=True)
print(df["open"].max())
print(df["open"].min())
print(df["open"].mean())
出力は以下の通り。
1.112
1.1
1.1063076923076922
さっきまでの学習のおかげで瞬殺だった。
時間指定でデータを取得
timestampがあるんだから、やっぱり時間指定してデータが欲しいよね。
これに関しては全く思いつかなかったから調べた。
まずはdf[condition]
の形式。
どうやら条件を満たすものを取得できるらしい。
それと注意すべきがdf['timestamp'] = pd.to_datetime(df['timestamp'])
の処理。
元々は文字列型だからそれをDateTime型に変換しないと<=
などが使えない。
import pandas as pd
# 事前に蓄えていたデータ
df = pd.read_json('5min_data.json')
# APIで取得するはずのデータ
next_data = {"timestamp": "2024-10-25 11:00:00+00:00", "open": 1.1120, "high": 1.1140, "low": 1.1110, "close": 1.1130, "volume": 1300}
next_df = pd.DataFrame([next_data])
df = pd.concat([df, next_df], ignore_index=True)
df['timestamp'] = pd.to_datetime(df['timestamp'])
start_time = "2024-10-25 10:10:00+00:00"
end_time = "2024-10-25 10:40:00+00:00"
filtered_df = df[(df['timestamp'] >= start_time) & (df['timestamp'] <= end_time)]
print(filtered_df)
出力は以下の通り。
timestamp open high low close volume
2 2024-10-25 10:10:00+00:00 1.1025 1.104 1.1015 1.1035 1050
3 2024-10-25 10:15:00+00:00 1.1035 1.105 1.1025 1.1045 950
4 2024-10-25 10:20:00+00:00 1.1045 1.106 1.1035 1.1055 980
5 2024-10-25 10:25:00+00:00 1.1055 1.107 1.1045 1.1065 1000
6 2024-10-25 10:30:00+00:00 1.1065 1.108 1.1055 1.1075 1200
7 2024-10-25 10:35:00+00:00 1.1075 1.109 1.1065 1.1085 1150
8 2024-10-25 10:40:00+00:00 1.1085 1.110 1.1075 1.1095 1100
次がquery
メソッドを使ったパターン。出力は先ほどと全く同じ。
df[conditions]
は小規模データにquery
メソッドは大規模データに対してのパフォーマンスが向上するらしい。
query
メソッドの方が見やすいから好きなんだけどなー。。
import pandas as pd
# 事前に蓄えていたデータ
df = pd.read_json('5min_data.json')
# APIで取得するはずのデータ
next_data = {"timestamp": "2024-10-25 11:00:00+00:00", "open": 1.1120, "high": 1.1140, "low": 1.1110, "close": 1.1130, "volume": 1300}
next_df = pd.DataFrame([next_data])
df = pd.concat([df, next_df], ignore_index=True)
df['timestamp'] = pd.to_datetime(df['timestamp'])
start_time = "2024-10-25 10:10:00+00:00"
end_time = "2024-10-25 10:40:00+00:00"
# @で変数を参照できる
filtered_df = df.query("timestamp >= @start_time and timestamp <= @end_time")
print(filtered_df)
さいごに
Pandas触ってみたけど、めちゃくちゃ色々なことが出来るなという印象。
多分まだPandasの1%くらいしか理解していないんだろうけど、それでも便利なのはわかった。
これから色々なケースを試す時が来るだろうから、また1か月後くらいにこの記事を見直して、さらに深くPandasを学びたいと思った。
ではまた
Discussion