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

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

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

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

Q&A

解決済

2回答

1206閲覧

Python データフレームにフィルタをかけた後、指定列に数値を入力。これを何回か違う条件で繰り返したい。

Odakyu.S

総合スコア1

Python

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

0グッド

0クリップ

投稿2020/05/05 22:49

前提・実現したいこと

B列[XYZ_MA60]とC列[XYZ_MA120]を比較して、該当行がB>=CならD列[XYZ_MA60/120]の該当行に1を代入し、
そうでなければ(B<C)、D列[XYZ_MA60/120]の該当行に-1を代入したいです。
データ数は毎回変化します。

イメージ説明

発生している問題・エラーメッセージ

条件に該当する行のD列に数値を追加していくのに、どう書けば良いかがわかりません。

試したこと

df_gc=df[df['XYZ_MA60']>=df['XYZ_MA120']]
でフィルタをかけれることは分かったのですが、そこからD列の該当行に1を追加する方法が分かりませんでした。
assignを使うのでしょうか?
また、繰り返しでfor文を使うのでしょうか?
お知恵をお貸しください。よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

ベストアンサー

この手の処理でループを使う必要は全くありません。むしろパフォーマンス的にはできるだけ使わない事を推奨します。

df_gc=df[df['XYZ_MA60']>=df['XYZ_MA120']]
でフィルタをかけれることは分かったのですが、そこからD列の該当行に1を追加する方法が分かりませんでした。

上記の場合.loc[] を使って

Python

1df.loc[df['XYZ_MA60']>=df['XYZ_MA120'], 'XYZ_M60/120'] = 1

となります。
(ちょっと補足)
このmethodは.loc[行、列]のように指定することで、戻り値として Viewと呼ばれる元のデータフレームの一部を切り出したものを返します。
このViewは元のDataFrameのデータに対する参照となりますので、Viewにデータを直接書き込むことで元のデータフレームを更新することが出来ます。
今回の場合は df['XYZ_MA60']>=df['XYZ_MA120']にて該当する行をTrueとした Boolean配列 が得られますのでこのデータを行に指定、、'XYZ_M60/120'を列を指定することで該当の位置にデータを書き込むことができるようになります。
(ここまで)

あとは(B<C)、D列[XYZ_MA60/120]の該当行に-1を入れる処理を追加して

Python

1df.loc[df['XYZ_MA60']>=df['XYZ_MA120'], 'XYZ_M60/120'] = 1 2df.loc[df['XYZ_MA60']<df['XYZ_MA120'], 'XYZ_M60/120'] = -1

となります。

投稿2020/05/06 02:39

編集2020/05/06 02:52
magichan

総合スコア15898

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

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

Odakyu.S

2020/05/06 03:05 編集

magichan様 ご回答くださりありがとうございました。 上記コードで無事処理することができました。 locの使い方を勉強します。 補足説明もわかりやすく、大変助かりました。ありがとうございます。
guest

0

Python

1import itertools 2 3idx_list = [idx for nums1, idx in enumerate("B行の数値たち")] 4 5for lft, rght, idx in itertools.product("B行の数値たち", "C行の数値たち", idx_list): 6 if float(lft) > float(rght): 7 "D行idx番目に1を入れる" 8 df.iat[3, idx] = 1 9 else: 10 "D行idx番目に-1を入れる" 11 df.iat[3, idx] = -1

投稿2020/05/05 23:21

編集2020/05/06 00:47
ForestSeo

総合スコア2722

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

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

Odakyu.S

2020/05/06 00:09 編集

Hieda-K様 早速ご回答くださりありがとうございました。 二点質問なのですが、最後の"D列idx番目に1を入れる"の文章のところで、実際に[XYZ_MA60/120]の列に数値を自動入力させるためには、どうコードを書けば良いのでしょうか? あと、"B列の数値たち"はdf['XYX_60MA']と言うことで良いのでしょうか? 初心者的質問で申し訳ありませんが、よろしくお願いいたします。
Odakyu.S

2020/05/06 01:32 編集

Hieda-K様 ご丁寧にご回答ありがとうございます。 現在、Jupyter Notebookを使っていて、pandas、numpyを使用しています。 Hieda-K様からいただいたコードを下記のように記載したところ、以下のエラーが出ました。 "B行の数値たち"の部分の私の入力方法が悪いでしょうか? エラーメッセージの下に私が書いたコードを付けました。 何度も初歩的なことをお聞きしてしまって申し訳ありません。 <エラーメッセージ> --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-25-1d0e62647cce> in <module> 9 else: 10 #"D行idx番目に-1を入れる" ---> 11 df.iat[3, idx] = -1 ValueError: iAt based indexing can only have integer indexers --------------------------------------------------------------------------- <私が書いたコード全文> import numpy as np import pandas as pd df=pd.read_csv(r"D:\PC_User\デスクトップ\test_data.csv") import itertools idx_list = [idx for nums1, idx in enumerate(df['XYZ_MA60'])] for lft, rght, idx in itertools.product(df['XYZ_MA60'], df['XYZ_MA120'], idx_list): if float(lft) >= float(rght): #"D行idx番目に1を入れる" df.iat[3, idx] = 1 else: #"D行idx番目に-1を入れる" df.iat[3, idx] = -1
ForestSeo

2020/05/06 02:18 編集

idx_list = [idx for nums1, idx in enumerate(df['XYZ_MA60'])] じゃなくて idx_list = [idx for idx, nums in enumerate(df['XYZ_MA60'])] でいけるかも
Odakyu.S

2020/05/06 02:00

Hieda-K様 たびたび申し訳ありません。 上記、idx_list = [idx for idx, nums in enumerate(df['XYZ_MA60'])]に修正したところ、エラーとなりました。 エラーメッセージは ------------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-28-025dcaa1d91f> in <module> 9 else: 10 #"D行idx番目に-1を入れる" ---> 11 df.iat[3, idx] = -1 ~\anaconda3\lib\site-packages\pandas\core\indexing.py in __setitem__(self, key, value) 2191 key = list(self._convert_key(key, is_setter=True)) 2192 key.append(value) -> 2193 self.obj._set_value(*key, takeable=self._takeable) 2194 2195 ~\anaconda3\lib\site-packages\pandas\core\frame.py in _set_value(self, index, col, value, takeable) 3026 try: 3027 if takeable is True: -> 3028 series = self._iget_item_cache(col) 3029 return series._set_value(index, value, takeable=True) 3030 ~\anaconda3\lib\site-packages\pandas\core\generic.py in _iget_item_cache(self, item) 3597 ax = self._info_axis 3598 if ax.is_unique: -> 3599 lower = self._get_item_cache(ax[item]) 3600 else: 3601 lower = self._take_with_is_copy(item, axis=self._info_axis_number) ~\anaconda3\lib\site-packages\pandas\core\indexes\base.py in __getitem__(self, key) 3928 if is_scalar(key): 3929 key = com.cast_scalar_indexer(key) -> 3930 return getitem(key) 3931 3932 if isinstance(key, slice): IndexError: index 4 is out of bounds for axis 0 with size 4 ---------------------------------------------------------------------------- でした。どこに問題があるのでしょうか。 お手を煩わせてしまい、本当に申し訳ありません。
ForestSeo

2020/05/06 02:21 編集

df.iat[3, idx] = 1と df.iat[3, idx] = -1 を df.iat[idx, 3] = 1 df.iat[idx, 3] = -1 でした。 すみませんy xの順ですね numpyとごっちゃになってました
Odakyu.S

2020/05/06 02:58

Hieda-K様 何度もお聞きしてすみませんでした。 その都度、ご回答くださりありがとうございました。 いただいた修正でもまだエラーが出ますが、Hieda-K様のアプローチの仕方も勉強します。 2行で処理できるご回答を他の方からいただきましたので、次に進みたいと思います。 本当にありがとうございました。
ForestSeo

2020/05/06 03:06

すみません勉強不足で
Odakyu.S

2020/05/06 03:20

いえ、こちらこそ勉強不足で申し訳ありませんでした。 またよろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問