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

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

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

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

3回答

1778閲覧

pandasのデータフレームにおけるループ処理の効率向上

taro_yamada

総合スコア55

Python

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

1クリップ

投稿2020/10/14 15:28

編集2020/10/15 12:09

時系列データから株価が次にどちらの方向に動いたかサインを出すプログラムを書いています。
今のDF2を作ってループの中でループさせるやり方が非常に効率が悪いと思っていますが、いい書き方がわかりません。
初歩的な質問だと思いますが、pandasのレベルがなかなか向上せずに困っています。
どなたかご教示いただけないでしょうか?

python

1 2 df = df.reset_index(drop=True) 3 4 for i, row in df.iterrows(): 5 t = pushList.objects.get(pushList_id=df.loc[i, 'pushList_id']) 6 time = df.loc[i, 'CurrentPriceTime'] + datetime.timedelta(hours=9) 7 timecheck = time + datetime.timedelta(seconds=30) 8 if time.time() > END_TIME: #15時を超えていたらelseにとんで0をいれる 9 t.nextDirect = 0 # 0は時間外 10 t.save() 11 elif time.time() < START_TIME: 12 t.nextDirect = 0 # 0は時間外 13 t.save() 14 elif RESTSTART_TIME < time.time() < RESTEND_TIME: 15 t.nextDirect = 0 # 0は時間外 16 t.save() 17 else: 18 df2 = df[(df.SymbolName == df.loc[i, 'SymbolName']) & (df.index > i)] # 同じ銘柄かつiよりあとのレコードでDF2を作成 19 df2 = df2.reset_index(drop=True) 20 for i2, row2 in df2.iterrows(): 21 time2 = df2.loc[i2, 'CurrentPriceTime'] + datetime.timedelta(hours=9) # 比較対象のレコードの時間を格納 22 if time2.time() > timecheck.time(): 23 t.nextDirect = 3 #3は30秒間変化なし 24 t.save() 25 break 26 elif time2.time() > END_TIME: 27 t.nextDirect = 0 # 0は時間外 28 t.save() 29 break 30 elif RESTSTART_TIME < time2.time() < RESTEND_TIME: 31 t.nextDirect = 0 # 0は時間外 32 t.save() 33 break 34 else: 35 if df.loc[i, 'CalcPrice'] > df2.loc[i2, 'CalcPrice']: #CurrentQtyがiレコードのものより小さければ 36 t.nextDirect = 1 # 1が下がった 37 t.save() 38 break 39 elif df.loc[i, 'CalcPrice'] < df2.loc[i2, 'CalcPrice']: 40 t.nextDirect = 2 # 2は上がった 41 t.save() 42 break 43 44 if i % 100 == 0: 45 print(str(i) + "レコードまで処理") 46 print(datetime.datetime.now())

python

1pushList_id Symbol SymbolName Exchange ExchangeName CurrentPrice CurrentPriceTime CurrentPriceChangeStatus CurrentPriceStatus CalcPrice ... Sell6Price Sell6Qty Sell7Price Sell7Qty Sell8Price Sell8Qty Sell9Price Sell9Qty TotalMarketValue UnderBuyQty 20 4ab06a34-48af-46ca-9be9-283789524fa8 1447 ITbookホールディングス 1 東証マザーズ 0 2020-09-24 08:08:14.667339+09 NaN -1 915 ... 915 3600 916 6300 918 200 919 200 18123314415 215000 31 733360c1-7b3a-400a-971b-7d376277f7dc 7044 ピアラ 1 東証1部 0 2020-09-24 08:08:16.007247+09 NaN -1 2480 ... 2525 100 2536 300 2549 100 2560 400 17636966400 18200 42 8bf71bef-1a13-42ea-a23e-232c45176d09 3050 DCMホールディングス 1 東証1部 0 2020-09-24 08:08:17.408563+09 NaN -1 1525 ... 1564 700 1565 200 1566 300 1568 1000 244818443100 131000 53 e9760a1a-741c-482c-abd0-994b0ac78ebc 3776 ブロードバンドタワー 1 東証JQス 0 2020-09-24 08:08:17.692836+09 NaN -1 605 ... 634 200 635 3200 637 200 638 8100 36380767500 511200 64 07f99027-d7a9-45e4-ab78-891b3864e5e9 4722 フューチャー 1 東証1部 0 2020-09-24 08:08:18.171276+09 NaN -1 2298 ... 2300 800 2309 900 2310 500 2320 1300 109531872000 7000 75 ae39c2c4-fba3-458b-9c02-d52b5c609489 6580 ライトアップ 1 東証マザーズ 0 2020-09-24 08:08:18.471329+09 NaN -1 3135 ... 3180 300 3195 500 3200 1700 3220 100 9100905000 13100 86 782f5c31-57f0-4293-8de1-077388fd2963 3782 ディー・ディー・エス 1 東証マザーズ 0 2020-09-24 08:08:18.624487+09 NaN -1 310 ... 314 8900 315 13200 316 6000 317 7300 14225993000 243500 97 14aaf2a1-8274-47d4-bf98-803c3330a230 4308 Jストリーム 1 東証マザーズ 0 2020-09-24 08:08:20.357745+09 NaN -1 3835 ... 3845 100 3850 2200 3860 100 3870 300 53800064500 29800 108 717f1567-651c-4e69-8ddc-9f6f55098d31 4486 ユナイトアンドグロウ 1 東証マザーズ 0 2020-09-24 08:08:21.399333+09 NaN -1 1846 ... 1922 900 1927 100 1932 100 1935 100 6724239600 21800 119 e30a4b99-c464-40e0-9aa9-1645e2c8cef3 3776 ブロードバンドタワー 1 東証JQス 0 2020-09-24 08:08:22.101601+09 NaN -1 605 ... 634 200 635 3200 637 200 638 8100 36380767500 511300 1210 ca042bc9-aca7-458b-ad90-605143f69b26 4722 フューチャー 1 東証1部 0 2020-09-24 08:08:22.533328+09 NaN -1 2298 ... 2300 800 2309 900 2310 500 2315 100 109531872000 7000 1311 e6591f32-3ea9-43ed-873b-ce705438f0be 3998 すららネット 1 東証マザーズ 0 2020-09-24 08:08:24.452058+09 NaN -1 6220 ... 6220 3900 6230 300 6240 100 6250 2200 39435017700 24700 1412 fdd0c61e-0356-4a4f-90f1-901d2570d544 6579 ログリー 1 東証マザーズ 0 2020-09-24 08:08:25.284751+09 NaN -1 7320 ... 0 0 0 0 0 0 0 0 13684008000 17900 1513 c0cdf143-6c26-4ef5-9512-1cc0a2625b04 4347 ブロードメディア 1 東証JQス 0 2020-09-24 08:08:26.323568+09 NaN -1 115 ... 120 32900 121 40200 122 69100 123 71200 9101942145 899700 1614 a43c18c0-e016-4e8e-a734-fc1d5c5bad34 4347 ブロードメディア 1 東証JQス 0 2020-09-24 08:08:26.971614+09 NaN -1 115 ... 120 36900 121 40200 122 69100 123 71200 9101942145 899700 1715 999b66f7-385a-4ac0-b0fe-261d47607dd1 3776 ブロードバンドタワー 1 東証JQス 0 2020-09-24 08:08:28.060202+09 NaN -1 605 ... 634 200 635 3200 637 200 638 8100 36380767500 511300 1816 d85e324b-7021-471d-9e3e-925542a58fa0 8226 理経 1 東証2部 0 2020-09-24 08:08:28.129255+09 NaN -1 277 ... 279 6100 280 11600 281 3900 282 14500 4297577717 540800 1917 70ec8f01-d75d-4b3c-bde4-6b5b6016291f 6579 ログリー 1 東証マザーズ 0 2020-09-24 08:08:28.329728+09 NaN -1 7320 ... 0 0 0 0 0 0 0 0 13684008000 17900 2018 cf99c9e6-3907-4bff-a87a-f1b419f4c677 3681 ブイキューブ 1 東証1部 0 2020-09-24 08:08:28.345352+09 NaN -1 1791 ... 1796 100 1797 200 1798 300 1799 4900 43636282200 180100 2119 3dd74a5c-c200-4527-881d-4728e9129461 3776 ブロードバンドタワー 1 東証JQス 0 2020-09-24 08:08:28.429994+09 NaN

python

1Index(['pushList_id', 'Symbol', 'SymbolName', 'Exchange', 'ExchangeName', 2 'CurrentPrice', 'CurrentPriceTime', 'CurrentPriceChangeStatus', 3 'CurrentPriceStatus', 'CalcPrice', 'PreviousClose', 'PreviousCloseTime', 4 'ChangePreviousClose', 'ChangePreviousClosePer', 'OpeningPrice', 5 'OpeningPriceTime', 'HighPrice', 'HighPriceTime', 'LowPrice', 6 'LowPriceTime', 'TradingVolume', 'TradingVolumeTime', 'VWAP', 7 'TradingValue', 'BidQty', 'BidPrice', 'BidTime', 'BidSign', 8 'MarketOrderSellQty', 'Sell1Time', 'Sell1Sign', 'Sell1Price', 9 'Sell1Qty', 'created_date_at', 'created_timestamp_at', 10 'updated_timestamp_at', 'AskPrice', 'AskQty', 'AskSign', 'AskTime', 11 'Buy10Price', 'Buy10Qty', 'Buy1Price', 'Buy1Qty', 'Buy1Sign', 12 'Buy1Time', 'Buy2Price', 'Buy2Qty', 'Buy3Price', 'Buy3Qty', 'Buy4Price', 13 'Buy4Qty', 'Buy5Price', 'Buy5Qty', 'Buy6Price', 'Buy6Qty', 'Buy7Price', 14 'Buy7Qty', 'Buy8Price', 'Buy8Qty', 'Buy9Price', 'Buy9Qty', 15 'MarketOrderBuyQty', 'OverSellQty', 'Sell10Price', 'Sell10Qty', 16 'Sell2Price', 'Sell2Qty', 'Sell3Price', 'Sell3Qty', 'Sell4Price', 17 'Sell4Qty', 'Sell5Price', 'Sell5Qty', 'Sell6Price', 'Sell6Qty', 18 'Sell7Price', 'Sell7Qty', 'Sell8Price', 'Sell8Qty', 'Sell9Price', 19 'Sell9Qty', 'TotalMarketValue', 'UnderBuyQty'], 20 dtype='object')

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

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

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

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

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

toast-uz

2020/10/14 22:33

このコードの動作確認に向いた、最初に与えるdfの例を提示お願いします。このくらいのボリュームのコードだと、コードだけ見て改善は困難で、改善前後の結果を見比べながら改善を考える必要があるためです。なお、dfが巨大な場合、適度に縮小ください。また、print(df)だけだと各列の型がわからないので、適宜補足説明お願いします。
toast-uz

2020/10/14 23:26 編集

pushListはご自分で作られたクラスインスタンスでしょうか? 最終的にpushListからは「銘柄」情報が消えて、上がった下がった時間外のみの情報になってしまいますが、元のdfとあわせて使うのでしょうか?
toast-uz

2020/10/14 23:28

データフレームの例示ありがとうございます。1行だけだと動作確認には不足ですので、10〜20行で、複数銘柄が混在しているような例をお願いします。
toast-uz

2020/10/14 23:39

取り掛かるのは半日〜1日後になりますので、他の回答者様が解決される可能性も高いですが、ご自分で検討できるように方向性を書いておきます。 ご承知のようにforループを排除してDataFrame丸ごと処理するのが速いですので、pushListは当面触らずに、DataFrameにpushListに入力する0/1/2の値を入れる列を作る方針がよいです。でもって、銘柄単位に処理をするというのはgroupbyでいけます。またDataFrameの行の差分をとることで、時間差や価格差をまずは求めてしまいます。そこまでしたら、個々の行だけ着目して、pushList(の列)が決定できます。これをforループをまわさずに、できればgroupbyのtransform機能を使って一気に処理をします。
taro_yamada

2020/10/15 12:12

ご質問ありがとうございます。 ちなみに、質問をあまり複雑にしたくなかったので、書きませんでしたが、同様に列を追加して、30秒後の騰落率、1分後の騰落率といった感じでさらに5列ほど追加したいと思っています。 コミットの回数を減らすために、1行分データを作成して、まとめてアップデートしたいと思っています。 こちらもループなしで処理できますでしょうか? もちろん、別の質問にした方がよければ改めます。
toast-uz

2020/10/15 12:25

別の質問にしましょう。というのは、teratailは、あくまでも、ご自分でコードを書く上で、どうしてもわからないところを質問するものです。丸投げはよく無いとされている場所です。そのため、まずは今回の質問のコードをご自分で咀嚼し、追加列をご自分でコーディングしてみて、その上でわからないことを質問する、という手順が望ましいからです。
taro_yamada

2020/10/15 12:31

大変失礼しました。 改めてコーディングしてみたいと思います。
taro_yamada

2020/10/16 11:41

すみません。 まずは今回の課題を解消するためのサンプルとなるコードをいただけると助かります。
guest

回答3

0

自己解決

解決できず、別の質問を立て直しました。

投稿2020/10/19 14:08

taro_yamada

総合スコア55

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

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

0

9:00から15:00の内11:30から12:30は0
同一銘柄のを上がったら2、下がったら1、変動なしのうち30秒以上は3、30秒以内は欠損にしています

python

1import datetime 2import io 3 4import pandas as pd 5 6data = """ 7,pushList_id,Symbol,SymbolName,Exchange,ExchangeName,CurrentPrice,CurrentPriceTime,CurrentPriceChangeStatus,CurrentPriceStatus,CalcPrice,...,Sell6Price,Sell6Qty,Sell7Price,Sell7Qty,Sell8Price,Sell8Qty,Sell9Price,Sell9Qty,TotalMarketValue,UnderBuyQty 80,4ab06a34-48af-46ca-9be9-283789524fa8,1447,ITbookホールディングス,1,東証マザーズ,0,2020-09-24 07:08:14.667339+09,,-1,915,...,915,3600,916,6300,918,200,919,200,18123314415,215000 91,733360c1-7b3a-400a-971b-7d376277f7dc,7044,ピアラ,1,東証1部,0,2020-09-24 08:08:16.007247+09,,-1,2480,...,2525,100,2536,300,2549,100,2560,400,17636966400,18200 102,8bf71bef-1a13-42ea-a23e-232c45176d09,3050,DCMホールディングス,1,東証1部,0,2020-09-24 08:08:17.408563+09,,-1,1525,...,1564,700,1565,200,1566,300,1568,1000,244818443100,131000 113,e9760a1a-741c-482c-abd0-994b0ac78ebc,3776,ブロードバンドタワー,1,東証JQス,0,2020-09-24 08:08:17.692836+09,,-1,605,...,634,200,635,3200,637,200,638,8100,36380767500,511200 124,07f99027-d7a9-45e4-ab78-891b3864e5e9,4722,フューチャー,1,東証1部,0,2020-09-24 08:08:18.171276+09,,-1,2298,...,2300,800,2309,900,2310,500,2320,1300,109531872000,7000 135,ae39c2c4-fba3-458b-9c02-d52b5c609489,6580,ライトアップ,1,東証マザーズ,0,2020-09-24 08:08:18.471329+09,,-1,3135,...,3180,300,3195,500,3200,1700,3220,100,9100905000,13100 146,782f5c31-57f0-4293-8de1-077388fd2963,3782,ディー・ディー・エス,1,東証マザーズ,0,2020-09-24 08:08:18.624487+09,,-1,310,...,314,8900,315,13200,316,6000,317,7300,14225993000,243500 157,14aaf2a1-8274-47d4-bf98-803c3330a230,4308,Jストリーム,1,東証マザーズ,0,2020-09-24 08:08:20.357745+09,,-1,3835,...,3845,100,3850,2200,3860,100,3870,300,53800064500,29800 168,717f1567-651c-4e69-8ddc-9f6f55098d31,4486,ユナイトアンドグロウ,1,東証マザーズ,0,2020-09-24 08:08:21.399333+09,,-1,1846,...,1922,900,1927,100,1932,100,1935,100,6724239600,21800 179,e30a4b99-c464-40e0-9aa9-1645e2c8cef3,3776,ブロードバンドタワー,1,東証JQス,0,2020-09-24 08:08:22.101601+09,,-1,606,...,634,200,635,3200,637,200,638,8100,36380767500,511300 1810,ca042bc9-aca7-458b-ad90-605143f69b26,4722,フューチャー,1,東証1部,0,2020-09-24 08:08:22.533328+09,,-1,2298,...,2300,800,2309,900,2310,500,2315,100,109531872000,7000 1911,e6591f32-3ea9-43ed-873b-ce705438f0be,3998,すららネット,1,東証マザーズ,0,2020-09-24 08:08:24.452058+09,,-1,6220,...,6220,3900,6230,300,6240,100,6250,2200,39435017700,24700 2012,fdd0c61e-0356-4a4f-90f1-901d2570d544,6579,ログリー,1,東証マザーズ,0,2020-09-24 08:08:25.284751+09,,-1,7320,...,0,0,0,0,0,0,0,0,13684008000,17900 2113,c0cdf143-6c26-4ef5-9512-1cc0a2625b04,4347,ブロードメディア,1,東証JQス,0,2020-09-24 08:08:26.323568+09,,-1,115,...,120,32900,121,40200,122,69100,123,71200,9101942145,899700 2214,a43c18c0-e016-4e8e-a734-fc1d5c5bad34,4347,ブロードメディア,1,東証JQス,0,2020-09-24 08:09:26.971614+09,,-1,115,...,120,36900,121,40200,122,69100,123,71200,9101942145,899700 2315,999b66f7-385a-4ac0-b0fe-261d47607dd1,3776,ブロードバンドタワー,1,東証JQス,0,2020-09-24 08:08:28.060202+09,,-1,605,...,634,200,635,3200,637,200,638,8100,36380767500,511300 2416,d85e324b-7021-471d-9e3e-925542a58fa0,8226,理経,1,東証2部,0,2020-09-24 08:08:28.129255+09,,-1,277,...,279,6100,280,11600,281,3900,282,14500,4297577717,540800 2517,70ec8f01-d75d-4b3c-bde4-6b5b6016291f,6579,ログリー,1,東証マザーズ,0,2020-09-24 08:08:28.329728+09,,-1,7320,...,0,0,0,0,0,0,0,0,13684008000,17900 2618,cf99c9e6-3907-4bff-a87a-f1b419f4c677,3681,ブイキューブ,1,東証1部,0,2020-09-24 08:08:28.345352+09,,-1,1791,...,1796,100,1797,200,1798,300,1799,4900,43636282200,180100 27""" 28 29df = pd.read_csv(io.StringIO(data), index_col=0) 30 31df 32 33df["CurrentPriceTime"] = pd.to_datetime(df["CurrentPriceTime"]).dt.tz_localize(None) 34 35InTime= df["CurrentPriceTime"].dt.time.apply( 36 lambda d: (datetime.time(8) < d < datetime.time(11, 30)) 37 | (datetime.time(12, 30) < d < datetime.time(15)) 38) 39 40df1 = df.loc[:, ["SymbolName", "CurrentPriceTime", "CalcPrice"]] 41 42df1 43 44df_diff = df1.groupby("SymbolName").diff() 45 46# 上昇2、下降1、変動なし3、欠損None 47df_diff["Sign"] = df_diff["CalcPrice"].apply((lambda x: 1 if x < 0 else 2 if x > 0 else 3 if x == 0 else None)) 48 49# 30秒以内変動がないものを欠損 50df_diff["Sign"] = df_diff["Sign"].mask((df_diff["CurrentPriceTime"] < pd.Timedelta(seconds=30)) & (df_diff["Sign"] == 3)) 51 52# 時間外を0 53df_diff.loc[~InTime, "Sign"] = 0 54 55df["Sign"] = df_diff["Sign"] 56 57df

投稿2020/10/18 03:39

編集2020/10/18 12:43
barobaro

総合スコア1286

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

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

taro_yamada

2020/10/18 15:27 編集

一つ、仕様でうまくお伝えできていないところがありました。 次に株価が上がるというの部分ですが、pushデータ自体は何度も送られてくるので、同じ金額が続いた後に上がったか下がったかを判定したいと思っています。 下の例でお話しすると、2行目のSIGNも今は、NONEが入っていると思いますが、3行後には値段が上がるので、2を返すようにしたいと思っています。 なかなか上手くお伝えできなくてすみません。 Symbol SymbolName Exchange ExchangeName CurrentPrice CurrentPriceTime Sign 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1402 00:00.6 3 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1402 00:00.7 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1402 00:00.9 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1402 00:01.1 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1403 00:01.4 2 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1403 00:01.8 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1403 00:01.9 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1406 00:02.1 2 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1401 00:02.5 1 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1401 00:02.8 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1417 00:03.0 2 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1417 00:03.2 3276 譌・譛ャ邂。逅そ繝ウ繧ソ繝シ 1 譚ア險シシ鷹Κ 1417 00:03.8
taro_yamada

2020/10/18 15:35

また、逆に、最初にsign1を出している行(00:02:5)については、2行下で値段が上がるので、サインとしては2を返すようにしたいです。
barobaro

2020/10/18 23:22

文字化けしていて意味がわかりません 別途質問立ててください
barobaro

2020/10/18 23:26

またサンプルと希望する結果の例をご提示ください
taro_yamada

2020/10/19 14:07

質問を立て直しました。 本当にすみません。
guest

0

以下に示します。細かい部分はコードにコメントを入れています。
ループを全く使わない例となっています。ただし、細かくは、同じ銘柄で30秒以内に同じ価格が出てきた場合、元のコードと処理が異なっていると思います。

上記を放置した理由として2点です。

  • まずはループを全く使わないコードを確認してほしかった。
  • 元のコードは、同じ銘柄で30秒以内に同じ価格が出てきた場合、何もしない処理になっているが、それで質問者様の意図通りなのかが疑問であった。
  • 実際の利用シーンを考えると、本来は、準リアルタイムで逐次で情報が来る中でSignをどう与えるかが本来は問われているのではないか。そうすると、そもそも一気にループ処理するのではなく、逐次で全銘柄の最終価格一覧と比較して処理をすることが必要になる。逐次処理に拡張することを前提とした場合と、一括処理だけを考えた場合で、放置した部分のコードの方針が大きく異なる。よって、いまの段階では放置することにした。

ということで、まずはこれで回答とします。この内容を咀嚼し、それをもとにご自分で様々なトライをしていただき、また新たな理解の最前線でご質問をお願いします。

Python

1import pandas as pd 2import io 3 4# 各時刻を時刻型で用意しておく(処理するデータの日付にあらかじめあわせる) 5START_TIME = pd.to_datetime('2020-09-24 08:00:00+09') 6RESTSTART_TIME = pd.to_datetime('2020-09-24 15:15:00+09') 7RESTEND_TIME = pd.to_datetime('2020-09-24 16:15:00+09') 8END_TIME = pd.to_datetime('2020-09-25 05:30:00+09') 9 10# 例示されたデータは、コードの場合分けをあまり確認できないため、一部修正 11data = (''' 12pushList_id Symbol SymbolName Exchange ExchangeName CurrentPrice CurrentPriceTime CurrentPriceChangeStatus CurrentPriceStatus CalcPrice ... Sell6Price Sell6Qty Sell7Price Sell7Qty Sell8Price Sell8Qty Sell9Price Sell9Qty TotalMarketValue UnderBuyQty 134ab06a34-48af-46ca-9be9-283789524fa8 1447 ITbookホールディングス 1 東証マザーズ 0 2020-09-24 07:08:14.667339+09 NaN -1 915 ... 915 3600 916 6300 918 200 919 200 18123314415 215000 14733360c1-7b3a-400a-971b-7d376277f7dc 7044 ピアラ 1 東証1部 0 2020-09-24 08:08:16.007247+09 NaN -1 2480 ... 2525 100 2536 300 2549 100 2560 400 17636966400 18200 158bf71bef-1a13-42ea-a23e-232c45176d09 3050 DCMホールディングス 1 東証1部 0 2020-09-24 08:08:17.408563+09 NaN -1 1525 ... 1564 700 1565 200 1566 300 1568 1000 244818443100 131000 16e9760a1a-741c-482c-abd0-994b0ac78ebc 3776 ブロードバンドタワー 1 東証JQス 0 2020-09-24 08:08:17.692836+09 NaN -1 605 ... 634 200 635 3200 637 200 638 8100 36380767500 511200 1707f99027-d7a9-45e4-ab78-891b3864e5e9 4722 フューチャー 1 東証1部 0 2020-09-24 08:08:18.171276+09 NaN -1 2298 ... 2300 800 2309 900 2310 500 2320 1300 109531872000 7000 18ae39c2c4-fba3-458b-9c02-d52b5c609489 6580 ライトアップ 1 東証マザーズ 0 2020-09-24 08:08:18.471329+09 NaN -1 3135 ... 3180 300 3195 500 3200 1700 3220 100 9100905000 13100 19782f5c31-57f0-4293-8de1-077388fd2963 3782 ディー・ディー・エス 1 東証マザーズ 0 2020-09-24 08:08:18.624487+09 NaN -1 310 ... 314 8900 315 13200 316 6000 317 7300 14225993000 243500 2014aaf2a1-8274-47d4-bf98-803c3330a230 4308 Jストリーム 1 東証マザーズ 0 2020-09-24 08:08:20.357745+09 NaN -1 3835 ... 3845 100 3850 2200 3860 100 3870 300 53800064500 29800 21717f1567-651c-4e69-8ddc-9f6f55098d31 4486 ユナイトアンドグロウ 1 東証マザーズ 0 2020-09-24 08:08:21.399333+09 NaN -1 1846 ... 1922 900 1927 100 1932 100 1935 100 6724239600 21800 22e30a4b99-c464-40e0-9aa9-1645e2c8cef3 3776 ブロードバンドタワー 1 東証JQス 0 2020-09-24 08:08:22.101601+09 NaN -1 606 ... 634 200 635 3200 637 200 638 8100 36380767500 511300 23ca042bc9-aca7-458b-ad90-605143f69b26 4722 フューチャー 1 東証1部 0 2020-09-24 08:08:22.533328+09 NaN -1 2298 ... 2300 800 2309 900 2310 500 2315 100 109531872000 7000 24e6591f32-3ea9-43ed-873b-ce705438f0be 3998 すららネット 1 東証マザーズ 0 2020-09-24 08:08:24.452058+09 NaN -1 6220 ... 6220 3900 6230 300 6240 100 6250 2200 39435017700 24700 25fdd0c61e-0356-4a4f-90f1-901d2570d544 6579 ログリー 1 東証マザーズ 0 2020-09-24 08:08:25.284751+09 NaN -1 7320 ... 0 0 0 0 0 0 0 0 13684008000 17900 26c0cdf143-6c26-4ef5-9512-1cc0a2625b04 4347 ブロードメディア 1 東証JQス 0 2020-09-24 08:08:26.323568+09 NaN -1 115 ... 120 32900 121 40200 122 69100 123 71200 9101942145 899700 27a43c18c0-e016-4e8e-a734-fc1d5c5bad34 4347 ブロードメディア 1 東証JQス 0 2020-09-24 08:09:26.971614+09 NaN -1 115 ... 120 36900 121 40200 122 69100 123 71200 9101942145 899700 28999b66f7-385a-4ac0-b0fe-261d47607dd1 3776 ブロードバンドタワー 1 東証JQス 0 2020-09-24 08:08:28.060202+09 NaN -1 605 ... 634 200 635 3200 637 200 638 8100 36380767500 511300 29d85e324b-7021-471d-9e3e-925542a58fa0 8226 理経 1 東証2部 0 2020-09-24 08:08:28.129255+09 NaN -1 277 ... 279 6100 280 11600 281 3900 282 14500 4297577717 540800 3070ec8f01-d75d-4b3c-bde4-6b5b6016291f 6579 ログリー 1 東証マザーズ 0 2020-09-24 08:08:28.329728+09 NaN -1 7320 ... 0 0 0 0 0 0 0 0 13684008000 17900 31cf99c9e6-3907-4bff-a87a-f1b419f4c677 3681 ブイキューブ 1 東証1部 0 2020-09-24 08:08:28.345352+09 NaN -1 1791 ... 1796 100 1797 200 1798 300 1799 4900 43636282200 180100 32''') 33 34# データフレームをcsvから準備して時刻を時刻型にする 35df = pd.read_csv(io.StringIO(data.replace(' ', ','))) 36df['CurrentPriceTime'] = pd.to_datetime(df['CurrentPriceTime']) 37 38# 以上のコードは、質問者様環境の再現のためであり、記述する必要はない 39# ここからが実際の計算 40 41# 時間内かどうかは、データフレームのまま、いっきに判定して、'OnTime'列に結果を記載 42df_time = df['CurrentPriceTime'] 43df['OnTime'] = (df_time > START_TIME) & (df_time < RESTSTART_TIME) | (df_time > RESTEND_TIME) & (df_time < END_TIME) 44# 'OnTime'列=Falseなら'Sign'列=0、それ以外なら'Sign'列=UNDEFINEDを入れる 45UNDEFINED = 999 # NoneにするとSign列の型がintを保てないためUNDEFINEDとする 46df['Sign'] = df['OnTime'].astype(int) * UNDEFINED 47 48# 銘柄->時刻の2列を使ってソートする 49df = df.sort_values(['Symbol', 'CurrentPriceTime']) 50# 銘柄、時刻、価格の差分列を作る 51df[['dSymbol', 'dCurrentPriceTime', 'dCalcPrice']] = df[['Symbol', 'CurrentPriceTime', 'CalcPrice']].diff() 52# グループ化してから差分をとると処理が複雑なのであらかじめやっておく 53# 結果として銘柄が変わる場所での差分は意味を持たないことに注意 54# よって、銘柄の差分列で銘柄が変わったかどうか判定する 55# こういった「ソート」と「差分」により、一度に一つの行だけを注目して処理できるようにするのがコツ 56 57# 時間内で、同じ銘柄で30秒以内で価格も変わらない情報はノイズとして捨てる 58 59 60# 時間内で、同じ銘柄で時刻差が30秒以上なら'Sign'列を3にする 61# ただし、30秒以内で同じ価格が並んだ場合に、通しで30秒超えは判定不能 62df['Sign'] = df['Sign'].mask((df['Sign'] == UNDEFINED) & (df['dSymbol'] == 0) & (df['dCurrentPriceTime'] > pd.Timedelta(seconds=30)), 3) 63 64# 時間内で、同じ銘柄で価格が下がったら'Sign'列を1にする 65df['Sign'] = df['Sign'].mask((df['Sign'] == UNDEFINED) & (df['dSymbol'] == 0) & (df['dCalcPrice'] < 0), 1) 66 67# 時間内で、同じ銘柄で価格が上がったら'Sign'列を2にする 68df['Sign'] = df['Sign'].mask((df['Sign'] == UNDEFINED) & (df['dSymbol'] == 0) & (df['dCalcPrice'] > 0), 2) 69 70# この後、UNDEFINEDは除いて、'Sign'列をpushList変数に入れれば完成 71# pushListの型定義は質問に記載されていないので、その部分は質問者にて実装ください 72 73# 今回は上記でできるため、あえてgroupbyを使わなくてよい 74# 途中の作業列は残しておくが、削除することは簡単にできる 75# またindexは元のままなので、元のデータフレームの順番に戻すことも可能 76

投稿2020/10/16 13:31

toast-uz

総合スコア3266

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

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

taro_yamada

2020/10/16 14:12

ありがとうございます! コードを読んでみて、一つお伝え漏れしている情報があることに気づきました・・・ 今回の株の情報は、板の変動があるたびにデータが送られてくるので、CurrentPriceが動かないのにpushAPIのデータはひたすら送られてくること。 その上で、いくつ先のレコードかわからないけど、CurrentPriceが動いた時に、上に動いたか下に動いたか判定したいと考えています。 つまり、DIFFを使って一つに行だと判定しきれないと思われます! toast-uz様が考えてくれたコードをもとに私ももう少し考えてみたいと思います。
toast-uz

2020/10/16 14:20

「準リアルタイムで逐次で情報が来る中でSignをどう与えるかが本来は問われているのではないか。」という想定通りですね。全銘柄の最終価格一覧を維持更新しつつ処理をするとよいと思います。しかし、非同期処理まで考える必要が出てくるため、pushAPIの扱い方まで踏み込んで考える必要があります。今回のコードを参考に考えてみてください。
taro_yamada

2020/10/16 15:01

それが・・・ 1日のデータ取得が終わって、夜に解析するための前処理として考えています。 すみません・・・
toast-uz

2020/10/16 15:11

「CurrentPriceが動かないのにpushAPIのデータはひたすら送られてくる」けど「準リアルタイムではなく1日分をバッチ処理する」ということですね。だとしても、30秒価格が動かなかったかどうか、を知るには、全銘柄の(その時点の)最終価格一覧を持ち回って、舐めていく処理が必要です。上がった・下がった・時間外は今回のコードでできますが、30秒値動き無しだけは、forループでまわして地道に処理する必要があります。
taro_yamada

2020/10/16 15:32

df[['dSymbol', 'dCurrentPriceTime', 'dCalcPrice']] = df[['Symbol', 'CurrentPriceTime', 'CalcPrice']].diff() 上のコードは、レコードの差を示していると思っています。すなわち、CurrentPriceが動かない場合、0, '0:0:0.002', 0といった感じになると思います。 df['Sign'] = df['Sign'].mask((df['Sign'] == UNDEFINED) & (df['dSymbol'] == 0) & (df['dCurrentPriceTime'] > pd.Timedelta(seconds=30)), 3) そこで、この行を処理しても、次のレコードで値動きしなかったということで3を返してしまうような気がしています。 いかがでしょうか?
toast-uz

2020/10/16 15:39

動きは実際のデータで確かめてみてくだいさい。 今のコード(diff)だと1つ前の行との差分ですが、本来、30秒を判断するにはその時点での最新価格との差分を求める必要があります。たとえば、10秒ごとに同じ価格が来たら、1つ前の行との差分は10秒なので、今のコードだと延々とUNDEFINEDになるだけで、3は返しません。 なので「3を返してしまう」というのではなく「3を返せない」方向に間違っています。
taro_yamada

2020/10/17 01:36

# 各時刻を時刻型で用意しておく(処理するデータの日付にあらかじめあわせる) START_TIME = datetime.time(9,00,0,0) END_TIME = datetime.time(15,00,0,0) RESTSTART_TIME = datetime.time(11,30,0,0) RESTEND_TIME = datetime.time(12,30,0,0) print("教師信号追加開始(addAnswerB)") print("処理件数") print(len(df)) print(datetime.datetime.now()) df = df.reset_index(drop=True) # データフレームをcsvから準備して時刻を時刻型にする df['CurrentPriceTime'] = pd.to_datetime(df['CurrentPriceTime']) df['Symbol'] = df['Symbol'].astype(int) # 以上のコードは、質問者様環境の再現のためであり、記述する必要はない # ここからが実際の計算 # 時間内かどうかは、データフレームのまま、いっきに判定して、'OnTime'列に結果を記載 df_time = df['CurrentPriceTime'] + datetime.timedelta(hours=9) df['OnTime'] = (df_time > START_TIME) & (df_time < RESTSTART_TIME) | (df_time > RESTEND_TIME) & ( df_time < END_TIME) 試しているのですが、時刻のところで行き詰まってしまいました。 実際に使っているデータがUTC分ずれているので、全てon_timeがFalseになってしまい、上記コードの通り修正してdatetimeをtimeに変換して処理したいのですが、df_timeがserious型なので比較できないというエラーで先に進めずにいます。 すみません。いい処理方法があればご教示ください。
toast-uz

2020/10/17 02:28

回答コードではSTART_TIMEなどにタイムゾーンをあてはめており、途中でタイムゾーン変換をしていません。同様にしたほうがよいでしょう。
taro_yamada

2020/10/17 10:53

dt_timeには、日付が複数入っているので、日付に関わらず9時から11時半と12時半から3時までのデータをTRUEにしたいのですが、pandasにdateの型がないので、合わせられずに困っています・・・
toast-uz

2020/10/17 11:00

そこは悩ましたかった部分です。データフレームから日付を取り出して、START_TIMEなどを設定するしかないと思いました。それを書くのが大変そうだったので、START_TIMEなどを日付決め打ちで定義しています。実際には最初に日付処理をして、START_TIMEなどを設定すべきでしょう。
taro_yamada

2020/10/17 19:33

元のDFを作成する際に、不要な時間帯のデータは取らないようにするしかなさそうですね・・・ ちょっとデータ取得からやり直してみます。
bsdfan

2020/10/17 23:09

df_time.dt.time()で時間部分だけとりだせますよ。 データフレームではなく、numpyのarrayになりますが。
barobaro

2020/10/18 02:27

df["CurrentPriceTime"].dt.time.apply( lambda d: (datetime.time(8) < d < datetime.time(11, 30)) | (datetime.time(12, 30) < d < datetime.time(15)) ) で判定できます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問