日本株の基礎指標(PERや配当利回り)をpythonでスクレイピングを使って取得する (2)
前回の続きです。前回は「みんなの株式」から、単一銘柄のPERや配当利回りをスクレイピングで取得しました。今回は複数銘柄の情報を統合してみます。
[1] DataFrameにまとめる
pandasのDataFrameに複数銘柄の情報をまとめます。pandasはデータ分析用のライブラリです。DataFrameはpandasの基本構造で表形式のデータです。
[1-1] pandasのインストール
pip3 install numpy --user pip3 install pandas --user
[1-2] DataFrameの作成
鉄道関係 5銘柄の情報を取得し、DataFrameにまとめます。get_basic_info
は前回の内容を関数化したものです。
jre_dict = get_basic_info(9020) # JR東日本 jrc_dict = get_basic_info(9022) # JR東海 jrw_dict = get_basic_info(9021) # JR西日本 tokyu_dict = get_basic_info(9005) # 東急 kintetsu_dict = get_basic_info(9041) # 近鉄 jre_sr = pd.Series(jre_dict.values(), index=jre_dict.keys(), name='JR東日本') jrc_sr = pd.Series(jrc_dict.values(), index=jrc_dict.keys(), name='JR東海') jrw_sr = pd.Series(jrw_dict.values(), index=jrw_dict.keys(), name='JR西日本') tokyu_sr = pd.Series(tokyu_dict.values(), index=tokyu_dict.keys(), name='東急') kintetsu_sr = pd.Series(kintetsu_dict.values(), index=kintetsu_dict.keys(), name='近鉄') df = pd.DataFrame([jre_sr, jrw_sr, jrc_sr, tokyu_sr, kintetsu_sr])
結果、以下のような内容にまとめることができました。
始値 | 高値 | 安値 | 配当利回り | ... | |
---|---|---|---|---|---|
JR東日本 | 6,510.0円 | 6,580.0円 | 6,479.0円 | 2.53% | ... |
JR東海 | 14,280.0円 | 14,450.0円 | 14,280.0円 | 1.04% | ... |
JR西日本 | 5,000.0円 | 5,078.0円 | 4,959.0円 | 3.59% | ... |
東急 | 1,372.0円 | 1,379.0円 | 1,360.0円 | 1.67% | ... |
近鉄 | 4,745.0円 | 4,770.0円 | 4,720.0円 | 1.05% | ... |
[2] 単位を削る
'円'や'%'などの単位が付与された状態ですが、平均値を出す場合など計算する際には邪魔になります。DataFrameから単位を削っていきます。
[2-1] 正規表現を使う
正規表現を使って、不要なものを削っていきます。
以下は株価(始値, 高値)の例です。カンマと円が不要なので削っていきます。株価は銘柄ごとに異なっており、5桁のものもあれば3桁のものもあるため、どれにも対応できるようにしています。
import re yen = '1,234.5円' # 正規表現で'円'より前の文字列を抽出 yen_re = re.search(r"([+-]?\d{1,3}(,\d{3})*\.\d+)円", yen) yen = yen_re.group(1) # カンマを削除 yen = value.replace(',', '') # 実数に変換 yen = float(yen) print(yen) # 1234.5
[2-2] すべての列に適用する
[2-1]と同様の処理を、すべての列に適用します。DataFrameのmapメソッドを使い、列ごとに変換処理を行っていきます。
[2-2-1] 変換用の関数を用意する
まずは、以下のような変換関数を用意します。円, 株といった単位ごとに関数を用意してもよいのですが、面倒なので全単位に対応できる関数を用意しました。
# 単位を削除する関数 def trim_unit(x): # 単位=円を削除 yen_re = re.search(r"(\d{1,3}(,\d{3})*\.\d+)円", x) if yen_re: value = yen_re.group(1) value = value.replace(',', '') return np.float64(value) # 単位=%を削除 perc_re = re.search(r"(\d+\.\d+)%", x) if perc_re: value = perc_re.group(1) return np.float64(value) # 単位=株を削除 stock_re = re.search(r"(\d{1,3}(,\d{3})*)株", x) if stock_re: value = stock_re.group(1) value = value.replace(',', '') return np.int64(value) # 単位=倍を削除 times_re = re.search(r"(\d+\.\d+)倍", x) if times_re: value = times_re.group(1) return np.float64(value) # 単位=百万円を削除 million_yen_re = re.search(r"(\d{1,3}(,\d{3})*)百万円", x) if million_yen_re: value = million_yen_re.group(1) value = value.replace(',', '') value = np.int64(value) * 1000000 return value # 単位=千株を削除 thousand_stock_re = re.search(r"(\d{1,3}(,\d{3})*)千株", x) if thousand_stock_re: value = thousand_stock_re.group(1) value = value.replace(',', '') value = np.int64(value) * 1000 return value return x
[2-2-2] map関数で各列に変換処理を行う
pandasのmap関数を使用して、上に挙げたtrim_unit
を各列に対して適用します。
# 各列に対して、trim_unitを適用する new_df = df.copy() for col in df.columns: new_df[col] = new_df[col].map(lambda v : trim_unit(v))
[3] 各列の統計量を算出する
[3-1] 平均値と標準偏差の算出
単位を削り数値に変換できたので、各列の平均値と標準偏差を求めます。
mean = new_df.mean() # 平均値 std = new_df.std() # 標準偏差
求めた平均値と標準偏差をDataFrameにまとめると、以下の結果が得られました。
statistics = pd.DataFrame( {'平均値': new_df.mean(), '標準偏差': new_df.std()})
平均値 | 標準偏差 | |
---|---|---|
始値 | 6381.4 | 4798.0 |
高値 | 6451.4 | 4858.9 |
安値 | 6359.6 | 4806.1 |
配当利回り | 1.976 | 1.088 |
単元株数 | 100 | 0 |
PER(調整後) | 18.738 | 14.714 |
PSR | 0.91 | 0.39 |
PBR | 1.118 | 0.628 |
出来高 | 1.081580e+06 | 5.990959e+05 |
時価総額 | 1.629025e+12 | 1.001244e+12 |
発行済株数 | 3.181594e+08 | 1.887879e+08 |
[3-2] 統計量と各銘柄データを結合
求めた統計量を、各銘柄のデータと結合して比較してみます。
ここで比較に役に立たないと思われるデータは削ります。また、出来高と時価総額は桁数が多いので、見やすい桁数になるように単位を変換します。
# 各銘柄のデータと統計量を結合する。 new_df2 = new_df.append(statistics.T) # 出来高と時価総額の単位を変換する。 new_df2['出来高'] = new_df2['出来高'] / 1.0e+3 new_df2['時価総額'] = new_df2['時価総額'] / 1.0e+12 new_df2 = new_df2.rename(columns= {'出来高': '出来高(千株)', '時価総額': '時価総額(兆円)'}) # 不要な列を削除する。 new_df2 = new_df2.drop(columns= ['始値', '高値', '安値', '単元株数', '発行済株数', '購入金額'])
以下だけで読み取れる情報は未だ少ないですが、近鉄のみPER, PBRが大きいと分かります。
配当利回り | PER(調整後) | PSR | PBR | 出来高(千株) | 時価総額(兆円) | 株主優待 | |
---|---|---|---|---|---|---|---|
JR東日本 | 2.53 | 12.39 | 0.83 | 0.77 | 1965.8 | 2.458450 | 株主優待割引券、自社施設サービス券、人間ドック割引券 |
JR東海 | 1.04 | 7.07 | 1.60 | 0.76 | 701.9 | 2.957130 | 株主優待乗車証 |
JR西日本 | 3.59 | 10.85 | 0.64 | 0.79 | 1247.9 | 0.970065 | 鉄道優待、グループ優待 |
東急 | 1.67 | 19.61 | 0.73 | 1.05 | 1104.6 | 0.856696 | 株主優待乗車証、自社グループ優待券 |
近鉄 | 1.05 | 43.77 | 0.75 | 2.22 | 387.7 | 0.902784 | 株主優待乗車証、自社施設割引券 |
平均値 | 1.98 | 18.74 | 0.91 | 1.12 | 1081.6 | 1.629025 | NaN |
標準偏差 | 1.09 | 14.71 | 0.39 | 0.63 | 599.1 | 1.001244 | NaN |
終わりに
今回は複数銘柄の基本指標を取得し、比較するところまで行いました。次回は、決算情報の取得を行います。
*1:Lorenzo CafaroによるPixabayからの画像