質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

1722閲覧

1つ目のデータと、それ以降のデータの算出計算が異なる場合の計算式の書き方

qsuke

総合スコア11

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/01/19 11:57

前提・実現したいこと

「平均足」という指標の計算をしたい。
(最初(厳密には2番め)のデータと、それ以降のデータとで、計算式が異なる場合の計算を、どのように行うか)

困っていること、及び該当のソースコード

以下のようなデータがあった場合、

Python

1# date open high low close 2#0 2020-01-14 1810 1849 1785 1807 3#1 2020-01-15 1800 1832 1776 1805 4#2 2020-01-16 1830 1857 1805 1833 5#3 2020-01-17 1864 1943 1813 1915

求めたい値を
・平均足の終値(HA_close)
・平均足の始値(HA_open)
とすると、求めたい計算式は以下のようになります。

平均足の終値(HA_close) = (当日始値+当日高値+当日安値+当日安値) / 4
→ df['HA_close'] = (df['open'] + df['high'] + df['low'] + df['close']) / 4

平均足の始値(HA_open)
【1日目の場合】※上記ケースだと2020-01-15
= (前日始値+前日高値+前日安値+前日終値) / 4
→ df['HA_open'] = (df['open'].shift(1) + df['high'].shift(1) + df['low'].shift(1) + df['close'].shift(1)) / 4

【2日目以降の場合】
= (前日の平均足の始値+前日の平均足の終値) / 2
→ (df['HA_open'].shift(1) + df['HA_close'].shift(1)) / 2

平均足の終値(HA_close)の方は単純な計算なので問題ないのですが、
平均足の始値(HA_open)の方は、最初(厳密には2番め)のデータと、それ以降のデータとで、計算式が異なるので、どのようにコードを書くのがいいか頭を悩ませています。

Python

1# date open high low close HA_open HA_close 2#0 2020-01-14 1810 1849 1785 1807 1813 3#1 2020-01-15 1800 1832 1776 1805 1813 1803 4#2 2020-01-16 1830 1857 1805 1833 1808 1831 5#3 2020-01-17 1864 1943 1813 1915 1820 1884 6

最終的には、上記のような形で出力させたく、以下のような形で書いたものの、HA_openは表示されませんでした。

Python

1for n in range(0, len(df)): 2 if n == 0: 3 df['HA_open'].iloc[n,:] = 0 4 elif n == 1: 5 df['HA_open'].iloc[n,:] = (df['open'].shift(1) + df['high'].shift(1) + df['low'].shift(1) + df['close'].shift(1)) / 4 6 else: 7 df['HA_open'] = (df['HA_open'].shift(1) + df['HA_close'].shift(1)) / 2

まだ知識が浅く、理解が間違っていたり、不足していたり、応用が効かない状態のため、質問の仕方自体もままならず、うまく伝わっていないかもしれませんが、アドバイスいただけると助かります。お手数おかけしますが、よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

pandas の動作としては、

  • 先頭行で Shift(1)した時の値:NaN
  • NaN 同士の値の平均:NaN
  • NaN を含めた数列の平均:NaN値を除いた数での平均

なので、そもそも条件文が不要ですし、1行目や2行目とそれ以外を分ける必要すらないのではないでしょうか。

  • 1日目:前の行がないので全ての'前日の平均足の始値'、'前日の平均足の終値'は共にNaNとなるので、その平均値である'当日 の平均足の始値'はNaNと計算される
  • 2日目:上記の計算より'前日の平均足の始値'はNaNとなるので、'前日の平均足の終値'との平均値である'当日の平均足の始値'はそのまま'前日の平均足の終値'と計算される

まとめるとこんな感じです。

Python

1import pandas as pd 2import numpy as np 3 4# 初期データ生成 5df = pd.DataFrame( 6 [['2020-01-14', 1810, 1849, 1785, 1807], 7 ['2020-01-15', 1800, 1832, 1776, 1805], 8 ['2020-01-16', 1830, 1857, 1805, 1833], 9 ['2020-01-17', 1864, 1943, 1813, 1915]], 10 columns=['date','open','high','low','close']) 11df = df.set_index('date') 12 13# ここから平均足の始値と平均足の終値の計算 14df['HA_open'] = np.nan 15df['HA_close'] = df.mean(axis=1) 16for idx, row in df.iterrows(): 17 df.loc[idx, 'HA_open'] = df.shift(1).loc[idx, ['HA_open', 'HA_close']].mean() 18 19print(df) 20# open high low close HA_open HA_close 21#date 22#2020-01-14 1810 1849 1785 1807 NaN 1812.75 23#2020-01-15 1800 1832 1776 1805 1812.750 1803.25 24#2020-01-16 1830 1857 1805 1833 1808.000 1831.25 25#2020-01-17 1864 1943 1813 1915 1819.625 1883.75

投稿2020/01/20 00:01

magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

qsuke

2020/01/20 17:20

詳細にありがとうございます! 上記で無事解決しました。 ご指摘いただいたように、難しく考えすぎていたように思います。。とてもすっきりしました。
guest

0

もう既に回答が出ているようですが、せっかく処理を作ってみたので掲載してみます。

好みで選んでもよいのではと思います。

python

1# 初期データ生成 2n_array = [ 3 ['2020-01-14', 1810, 1849, 1785, 1807], 4 ['2020-01-15', 1800, 1832, 1776, 1805], 5 ['2020-01-16', 1830, 1857, 1805, 1833], 6 ['2020-01-17', 1864, 1943, 1813, 1915] 7] 8df = pd.DataFrame(n_array, columns=['date','open','high','low','close']) 9df['HA_open'] = None 10df['HA_close'] = (df['open'] + df['high'] + df['low'] + df['close']) / 4 # 入れるの忘れてた 11 12# HA_open HA_close 計算 13df_len = len(df) 14for n in range(0, df_len): 15 if n == 0: 16 HA_open = 0 17 elif n == 1: 18 HA_open = (df.loc[n - 1][['open', 'high', 'low', 'close']].sum()) / 4 19 else: 20 HA_open = (df.loc[n - 1][['HA_open', 'HA_close']].sum()) / 2 21 22 df.loc[n, 'HA_open'] = HA_open 23 24df

投稿2020/01/19 12:42

編集2020/01/19 13:02
siruku6

総合スコア1382

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

siruku6

2020/01/19 13:03

ソースコードに一部書き忘れがあったので後から書き足しています...
guest

0

n=0,n=1の場合はループの中で処理する必要がなさそうですよね。
中の数式についてちゃんと確認しておらず動作チェックもしてませんが、雰囲気として次のような感じにできるのでないでしょうか。

df['HA_open'][0] = 0 df['HA_open'][1] = (df['open'].shift(1) + df['high'].shift(1) + df['low'].shift(1) + df['close'].shift(1)) / 4 for n in range(2, len(df)): df['HA_open'][n] = (df['HA_open'].shift(1) + df['HA_close'].shift(1)) / 2

なお、本件では必要なさそうに見えますが、場合分けを含む式を立てたい場合は三項演算子というのが使えます。
https://note.nkmk.me/python-if-conditional-expressions/

投稿2020/01/19 12:22

KojiDoi

総合スコア13671

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

qsuke

2020/01/19 13:05

さっそくご指摘いただきありがとうございます! 結構シンプルに行けるんですね…汗 さっそくアドバイスいただいた方法でやってみたところ、 KeyError: 'HA_open' というエラーが出て、それ以降も KeyError: "['HA_open'] not in index"  となってしまい、うまく処理しきれていませんでした。。 この計算部分以外のところで問題があるのでしょうか? df['HA_close']は問題なく計算できているので、df['HA_open']の計算部分だと思うのですが、何かこのエラーから気になる点はありますでしょうか?
KojiDoi

2020/01/19 13:49

dfにまだ'HA_close’列がないのですね。その場合は、df.assign()などで追加する必要があるでしょう。 もしくは、HA_closeに入れるべきデータを先に一次元配列として作り、 df['HA_close']=一次元配列の名前 のようにすればいけるのではないかと思います。
qsuke

2020/01/19 17:13

ご丁寧にありがとうございます! ただ、いろいろ調べてやってみているのですが、アドバイスいただいた内容をきちんと理解できないぐらいのレベルでして、どうにもうまくいかない状態です… かなり初歩的なレベルのことだと思いますので、今一度、基本的内容に立ち戻って、勉強しながらトライしてみたいと思います。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問