pagetakaBlog

最近リフォームと鳥取県日南町の記事多め。写真、PC、ネット等の話題も

Python修行:DataFrame特定項に欠損値のある行のCDと同じCD行全削除【スクリプト付き】

見出しで意味が通じていますでしょうか…不安。

【DataFrame特定項に欠損値のある行のCDと同じCD行全削除】
【DataFrame特定項に欠損値のある行のCDと同じCD行全削除】

今回は、データフレームz項をターゲットにして、欠損値になっていたらそのCDを取得後、重複排除し、データフレームとの差分を得るという、内容です。

前説:株式約定の無い項目をどうするか…。

東京証券取引所日報にふくまれる約定がない項目の扱いです。項目zに0を入れると0円ということになりかねず、他日・他項目との計算ができてしまいます。ありえない数字、たとえば-1を入れると、これも同様です。ふたつの例の場合、常に、0、-1があるとそれはこういう意味だ、とひと手間必要です。

爺のデータベースでは、約定がない項目は'\x00'を取得するようになります。株価・株数に関する項目をデータベースから取得すると(恐らく、'\x00'がどこかにあるので)設定は数値なのに結果は数字になっています。このままでは四則演算などができないので、数値化処理を施す結果、'\x00'は数値にならずエラーが出る…という流れです。'\x00'が見つかると必ず何らかの処理を行い、他の数字が数値化される妨げにならないようする…という流れで、切り抜けております…これが常道なのかどうかは不知です。

というようなことを考えるうち、欠損値(例えば、'\x00'、None、NaN)を見つけたら、それを含むCD全部処理から外せば…と思い始めました。この方向性が妥当かどうかは脇に置き、そういうことを実現するスクリプトを書こうと思いました。ある銘柄(CD)の10日間の売買で、1日約定がない日(=欠損値)があった場合、そのCDの10日分データを全体データから削除する…というコトです。

欠損値を含むCD取得し同CDを含む全行削除の流れ。

イメージはできるが、具体的に書けないということで、Microsoft:Copilotに教えてもらいながら、参考にして爺のスクリプトに落とし込みました。

Pandasの機能を使えばできそうです。isna、isinなど使えそうなメソッドもありそうです。

欠損値だけでなく特定値でも使用可能ですが、今回は欠損値に絞ります…。

  1. df:欠損値を含むDataFrameを用意する ※先頭の画像を参考に
  2. dfからz項欠損値の行からCDを取得し、CD重複排除→CDのみの配列(z項欠損値ID配列:an_np_array)。 ※爺の理解、第一関門
  3. z項欠損値CD配列を使い、dfに対し同じCDでなかったら残す(isinを~で否定) ※爺の理解、第二関門

Pythonスクリプト

pandasのimportが必要です。自己責任でお試しください。責任は負えませぬ…キッパリ。錯誤があるかもしれませぬ。優し目にご教示ください。

import pandas as pd

# Noneのあるリスト
a_list =[   ['A', 10, 20, None],
            ['B', None, 300, 0],
            ['C', 0, 15, None],
            ['A', 0, 15, 10],
            ['A', 50,None,None]
]
# リストからデータフレーム
df = pd.DataFrame(a_list, columns=['CD','x','y','z'])
print(df)

#   CD     x      y     z
# 0  A  10.0   20.0   NaN
# 1  B   NaN  300.0   0.0
# 2  C   0.0   15.0   NaN
# 3  A   0.0   15.0  10.0
# 4  A  50.0    NaN   NaN


# 項目zの値None=.isna()選択。選択結果に対しcD重複排除したdf_noneを得る
an_np_array = df[df['z'].isna()]['CD'].unique() # numpy.array ?
# print(an_np_array)
# ['A' 'C'] # ['ID'].unique() により 重複排除

# dfに対し、an_np_arrayにあるcDの値が含まれない(~)行を選択し、df_no_z_nanに入れる
df_no_z_nan = df[~df['CD'].isin(an_np_array)]

print(df_no_z_nan)
#   CD   x      y    z
# 1  B NaN  300.0  0.0

z項にNaN(None)があるCD(A,C)が全行削除できました。残っているのは、CD=Bだけです。Bのx=NaNですが、今回の除隊対象zではないので残っています。

関門:an_np_array = df[df['z'].isna()]['CD'].unique()、df_no_z_nan = df[~df['CD'].isin(an_np_array)]

an_np_array = df[df['z'].isna()]['CD'].unique()で削除用のリストができました。これは何故か、numpy.arrayという型になりましたが、気にせず進行…。
dfの内側にdfがあったりして、さらにisnaで何かして、その右に角カッコが続き、最後にunique…爺には複雑すぎます。日本語にして読んでみようとしますが…チョットムズイ…。

無理やり日本語(怪)にすると、(1)削除CDを求めるんだが、判定基準はdf['z'].isna()で、(2)CD重複を避けるためunique使ったよ~、というようなことかと思います。

次は、df_no_z_nan = df[~df['CD'].isin(an_np_array)]ですが…。(df_no_z_nan)=(df)-(an_p_array) という意味みたいです。「~」は否定の意味で使われ、isin(an_np_array)にあるものは排除するよ~と。
この結果、indexの0,2,3,4はCDがAかCだったので削除され、残ったのは、index1だけとなりました。めでたしめでたし…。

’’、None、NaN、'\x00'、など欠損値の扱いは面倒ですね。

すでにお気づきの方もおられるかと思いますが、この記事の中でNone、NaN、'\x00'をゴチャ混ぜに使ってます。すみません。本当は意味が異なる(はずです)。「''」も同様に要注意です。

爺が書いていることを鵜呑みにしないでください…(UPするなという声が聞こえますが…耳が遠い爺)。自己責任にてよろしくお願いします。

株式データのうち欠損値をどう扱うかはイロイロ検討対象かと思います。ある証券会社のサイトでは、約定の無い日のデータは、当該日を時系列データから削除して表で掲示してました。

今回、(1)最近N日間のデータを取得する、(2)そのN日間に欠損値がある銘柄コードは全件削除する、(3)残ったデータを使う、ということにしました。
あわせて、株を実際にやっておられる方がdfを見たら首を傾げるのかと思います。例ということでご容赦ください。始値が無ければすべて無しのはずですが、東京証券取引所日報は前場、後場を分けてPDFにしている都合上、前場では約定無いが、後場で約定ある、ということもあり、部分的な欠損値もあります。あしからずご了知のほど。