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

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

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

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

Python

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

Q&A

解決済

1回答

1420閲覧

AttributeError: ("'float' object has no attribute 'iloc'", 'occurred at index 0')の解決

qsuke

総合スコア11

if

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

Python

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

0グッド

1クリップ

投稿2020/01/20 17:36

編集2020/01/21 08:10

======【追記】======

最終的に実現したいこと

closeの値だけがあるところ(下表左列)に、
「closeの値の当日と前日との差が+、かつ前日と前々日の差も+」の場合'true'、
それ以外の場合が'-'と、右列に'signal'として挿入したいと考えています。

Python

1# close signal 2#0 1807 nan 3#1 1805 nan 4#2 1833 - 5#3 1905 true 6#4 1915 true

==================

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

以下のようなデータがあったとき(簡略化しています)、
条件にあった場合とそうでない場合を分けてシグナルを出したいと考えています。

Python

1# close 2#0 1807 3#1 1805 4#2 1833 5#3 1905 6#4 1915

最新の数字(上記の場合#4)がその前の数字よりも大きい場合'true'と表示させ、
それ以外は'-'としようと考え、以下のように書いたところ、

Python

1def signal(df): 2 if df['close'].iloc[-1] > df['close'].iloc[-2]: 3 return 'true' 4 else: 5 return '-' 6df['signal'] = df.apply(signal, axis=1)

AttributeError: ("'float' object has no attribute 'iloc'", 'occurred at index 0')
というエラーが表示されました。

df['close'].iloc[-1]単体で呼び出したら正しい数字が抽出されますし、
df['close'].iloc[-1] > df['close'].iloc[-2]も単体だと'true'と表示されたのに、
上記の条件文としたらエラーが表示されてしまう、という状況です。
かつ、エラーの意味がわからず、対処法に困っています。

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

======【追記】======
いろいろ調べてみたところ、

In: type(df['close'].iloc[-1])
Out: numpy.float64

と表示されており、.ilocで引っ張ってくるのがpandas形式になっていないのが原因のような気がしました。
※他の似たようなプログラムでうまく表示されているもののtypeは「pandas.core.series.Series」と表示されていたため

したがって、この場合、
・df['close'].iloc[-1] > df['close'].iloc[-2] をpandas形式になるように変更する
もしくは、
・df.applyのところで調整する?
ということが考えられるのかなと思いました。

が、その解決方法がわからないため、もしよろしければ、解決法をご教授いただけますと幸いです。まだ不明点等ありましたが、ご指摘ください。よろしくお願いします。

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

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

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

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

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

shiracamus

2020/01/20 23:16 編集

エラーメッセージにソースファイル名、行番号、ソースコードなどが表示されてませんか? 複数表示されてると思いますが、その中の自分のソースコードのエラー行には何が書いてあるのですか? 質問に書いてある行で間違いないですか?
t_obara

2020/01/21 01:26

signal(df)のdfが期待した値になっているのか確認してみてはいかがですか?それを見ると、提示されたメッセージが表示された理由がわかるかもしれません。
frodo821

2020/01/21 02:46

そもそもこれpandasのドキュメント見たらわかると思うんですけど、DataFrame.applyに渡した関数に渡されるのはDataFrameじゃないですよ。 気にしたことがなかったので合っているかわからない(というかそもそもドキュメントに記載がない)ので推測なんですが、Seriesが渡されているんじゃないでしょうか。
qsuke

2020/01/21 06:55

みなさま、ご指摘ありがとうございます。 エラーの該当箇所は記載している箇所で間違いはないのですが、 いろいろ調べてみたところ、 In: type(df['close'].iloc[-1]) Out: numpy.float64 と表示されており、.ilocで引っ張ってくるのがpandas形式になっていないのが原因のような気がしました。 ※他の似たようなプログラムでうまく表示されているもののtypeは「pandas.core.series.Series」と表示されていたため したがって、この場合、 ・df['close'].iloc[-1] > df['close'].iloc[-2] をpandas形式になるように変更する もしくは、 ・df.applyのところで調整する? ということが考えられるのかなと思いました。 が、その解決方法がわからないため、もしよろしければ、解決法をご教授いただけますと幸いです。まだ不明点等ありましたが、ご指摘ください。よろしくお願いします。
shiracamus

2020/01/21 07:26 編集

最後と最後から2個目を比較した結果をどこに代入するのですか? 最終的に手に入れたいデータ結果を書いていただけますか?
t_obara

2020/01/21 07:26

なので表示すれば何がきているのかわかりますし、このケースではapplyが適していないのでは?と思い至るとなお良いかと。 また、期待する結果を提示されると、適切なコードを提示してくれる人も出てくるかもしれません。
qsuke

2020/01/21 08:10

ご指摘ありがとうございます。 「最終的に実現したいこと」を追記してみました。 もともとの書き方が間違っていたかも(かつ、不足していた)ですが… closeの値だけがあるところ(下表左列)に、 「closeの値の当日と前日との差が+、かつ前日と前々日の差も+」の場合'true'、 それ以外の場合が'-'と、右列に'signal'として挿入したいと考えています。
shiracamus

2020/01/21 08:30

'true' か '-' なのに 'nan' があるのはなんなんですか?
qsuke

2020/01/21 08:41

差分を取る対象のclose値がないところは、計算できないので'nan'になるのかなと思い、そう記入しました。そこは、'-'でも問題はありません。
guest

回答1

0

ベストアンサー

すこし冗長ですが、こういうやり方もあります。

python

1df['signal'] = df['close'].rolling(2, min_periods=1).apply(lambda sr: 1 if sr[1:] and sr[1] > sr[0] else 0, raw=True).apply(lambda x: 'True' if x else '-')

DataFrame.rollingやSeries.rollingは、複数の行または列にわたって集計するための関数です。

これを少し見やすくして解説します。

python

1def aggregate(sr): 2 # `lambda sr: 1 if sr[1:] and sr[1] > sr[0] else 0`に相当する関数 3 # データがあり、かつ先にあるデータのほうが値が小さい場合1を返し、それ以外なら0を返す。 4 if sr[1:] and sr[1] > sr[0]: 5 return 1 6 return 0 7 8# 2行ずつデータを処理する。min_periods=1を指定しないと、最初の行が処理されない。 9rolling = df['close'].rolling(2, min_periods=1) 10 11# raw=Trueはpandas側の将来的な変更に対処するため。 12# なくても今は動くが、警告が出る。 13aggregated = df.apply(aggregate, raw=True) 14 15# aggregatedのそれぞれの値を'true'か'-'の文字列値に変えてdf['signal']に格納する。 16df['signal'] = aggregated.apply(lambda x: 'true' if x else '-')

見やすくして簡単にコメントをつけてみました。
複数行の処理にはrollingメソッドを使います。
今回の場合、'close'行のみ集計に使うので、df['close']でこの行のみに処理を行っています。

また、処理を2段階に分けているのは、rolling.applyに数値以外を返す関数は渡すことができないからです。

ここまでやるのであれば、おそらくfor文でやったほうがいいような気がします。
一応その場合も書いておきます。

forでやる場合

1x = [] 2for i, f in enumerate(df['close']): 3 if i == 0: 4 x.append('-') 5 continue 6 x.append('true' if f > df['close'].iloc[i-1] else '-') 7 8df['signal'] = x

こっちのほうが見た目明らかにすっきりしていますね。


前日と前々日の比較もするのでしたね。
でしたら、このように変えてください。

1行で書く場合

python

1df['signal'] = df['close'].rolling(3, min_periods=1).apply(lambda sr: 1 if sr[1:] and sr[1] > sr[0] and sr[2:] and sr[2] > sr[1] else 0, raw=True).apply(lambda x: 'True' if x else '-')

見やすくしてみたもの

python

1def aggregate(sr): 2 # `lambda sr: 1 if sr[1:] and sr[1] > sr[0] and sr[2:] and sr[2] > sr[1] else 0`に相当する関数 3 # データがあり、かつ先にあるデータのほうが値が小さい場合1を返し、それ以外なら0を返す。 4 if sr[1:] and sr[1] > sr[0] and sr[2:] and sr[2] > sr[1]: 5 return 1 6 return 0 7 8# 2行ずつデータを処理する。min_periods=1を指定しないと、最初の行が処理されない。 9rolling = df['close'].rolling(3, min_periods=1) 10 11# raw=Trueはpandas側の将来的な変更に対処するため。 12# なくても今は動くが、警告が出る。 13aggregated = df.apply(aggregate, raw=True) 14 15# aggregatedのそれぞれの値を'true'か'-'の文字列値に変えてdf['signal']に格納する。 16df['signal'] = aggregated.apply(lambda x: 'true' if x else '-')

forでやる方法

forでやる場合

1x = [] 2for i, f in enumerate(df['close']): 3 if i == 0 or i == 1: 4 x.append('-') 5 continue 6 x.append('true' if f > df['close'].iloc[i-1] and df['close'].iloc[i-1] > df['close'].iloc[i-2] else '-') 7 8df['signal'] = x

投稿2020/01/21 08:40

編集2020/01/21 09:11
frodo821

総合スコア322

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

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

qsuke

2020/01/22 06:05

ありがとうございます! 無事エラーを解消することができました。 いくつかアレンジしたいこともあるので、挑戦してみます。ご丁寧にありがとうございました!
frodo821

2020/01/22 06:09

これは株価のデータですかね?それなら、同じようにrollingメソッドを使って平均移動を求めたりもできます。 ドキュメントに詳しい使い方が書いてあるので、一度目を通してみてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問