2026/05/08
今回はデータフレームの結合から統計量の集計,ヒストグラムの描画・保存まで一気に行う.新しく登場する関数が多いので,まずは全体像を把握しておこう.
| 関数 | パッケージ | 役割 |
|---|---|---|
full_join() / inner_join() / left_join() |
dplyr |
二つのデータフレームを結合する |
if_else() |
dplyr |
条件に応じて異なる値を返す |
quantile() |
base R | 分位点(四分位など)を求める |
round() |
base R | 数値を指定した桁数で丸める |
across() + where() |
dplyr |
複数列に同じ処理を一括適用する |
write_csv() |
readr |
データフレームをCSVファイルに出力する |
seq() |
base R | 等差数列を生成する |
geom_histogram() |
ggplot2 |
ヒストグラムを描画する |
geom_vline() |
ggplot2 |
グラフに垂直線を追加する |
ggsave() |
ggplot2 |
直前に描画したグラフをファイルに保存する |
lag() |
dplyr |
一つ前の行の値を取得する(練習問題) |
mutate(),group_by(),summarize(),drop_na()なども引き続き使用する.join系関数(教科書コラム5.2)dplyrにはfull_join()関数を始め,結合を行うために用いるjoin系関数が用意されている.AとDPSデータBの結合を通じて,それぞれのjoin系関数の返り値を確認していこう.tibble()関数を使って二つのデータフレームを手動で作成している.full_join()関数inner_join()関数left_join()関数目標
simulation_dataフォルダにあるfinancial_data.csvをデータフレームfinancial_dataとして読み込んでみよう.head()関数により,financial_dataの冒頭6行を表示し,どのようなデータが収録されているか確認してみよう.codesである場合,読み込みたいfinancial_data.csvが格納されているsimulation_dataフォルダにアクセスするには,一個上の階層に一度戻る必要があり,それは..により実現可能である.simulation_dataフォルダに移動 (/simulation_data)し,/financial_data.csvで目的のファイルにアクセス可能である.fiscal_year_end: 決算年月 (YYYY-MM-DD形式)macc: 決算月数X: 当期純利益(百万円)TA: 資産合計(百万円)CFO: 営業活動によるキャッシュフロー(百万円)Xを基準化分析にあたっては,当期純利益Xそのものの分布ではなく,各企業の規模を統制して各観測値を横並びで比較可能にしたScaled Earnings (SE)の分布を考えよう.
\[ \underbrace{SE_{i,t}}_{\textbf{企業$i$の年度$t$のScaled Earnings}} = \frac{\overbrace{X_{i,t}}^{\textbf{企業$i$の年度$t$の当期純利益}}}{\text{各企業の規模の代理変数}} \]
この分析では,簡便的に各企業の発行する株式の時価総額 (\(=\) 株価 \(\times\) 発行済株式数)を規模の代理変数と捉え,分析を進めて行こう.
simulation_dataフォルダにあるstock_data.csvをstock_dataとして読み込んでみよう.stock_price: 株価shares_outstanding: 発行済株式数stock_dataに時価総額ME列の追加1e6は科学技術分野で一般的に用いられる科学的表記と呼ばれる表記法(教科書157頁)であり,\(1 \times 10^6 (= 1,000,000)\)と等しい.MEを計算する際,財務データと単位を揃えることを目的として1e6で除している.(stock_price * shares_outstanding) / 1000000とはしないこと!SE列も追加dplyrのif_else()関数を使って決算月数が12ヶ月の場合はSEを計算し,そうでなければ欠損値NAになるように工夫している.analysis_sampleを利用して分析を進めて行こう.目標
SEが欠損値となっている観測値を除外(\(=\) SEが計算可能な観測値のみを抽出)し,分析対象となるデータフレームをanalysis_sampleとして定義してみよう.drop_na()の使い方は,ここを参照.summarize()関数を使ってみよう目標
analysis_sampleを用いて,年度ごとにSEの平均値を算出し,それをMean列と名付けよう.year列とMean列から成るデータフレームをtable_1として定義しよう.table_1として定義.yearでグループ化.summarize関数を適用し,SEの平均値をmean(SE)により計算し,それをMeanと命名.quantile()関数の使い方quantile()関数を用いる.この関数は第一引数に入力データ(数値ベクトル),第二引数に求めたい分位点の値をパーセントでなく小数表示で代入する(教科書185頁).SEの第1四分位を求めたいならば,quantile(SE, 0.25)とすれば良い.across() は「複数の列に対して同じ処理を一括で適用する」ための関数である.where(is.double) は「小数を含む数値型<dbl>の列をすべて選択する」という意味である.このため,整数型<int>のN列は対象にならず,平均Meanや標準偏差SDなどの列だけが処理される.~ round(.x, 3) の部分は「無名関数(ラムダ関数)」と呼ばれる書き方である.
~ の後に書いた式が「その列に対してやる処理」を表している..x は「今処理している列の値」を指している(このように一時的に処理対象を表す記号をプレースホルダーという).across()関数で指定された各列を小数点第3位まで丸める」という意味になる.write_csv()関数を使ったデータフレームの出力readrのwrite_csv()関数を使って,先に作成したデータフレームtable_1をtablesフォルダに出力しよう.write_csv()関数の第一引数はデータフレーム名を入力し,第二引数でファイル名を指定する(教科書184頁).codesであることを前提にすれば,出力したいtablesフォルダへ移動するには,一個上の階層に一度戻る必要があり,それは..により実現可能である.tablesフォルダに移動 (/tables)し,table_1.csvという名前で出力 (/table_1.csv)すれば良いので,write_csv()関数の第二引数は,"../tables/table_1.csv"と指定する.SE)のヒストグラムggplot2を利用し,Scaled Earnings (SE)のヒストグラムを描画し,利益マネジメントの実態を明らかにしていこう.目標
analysis_sample内のSEについて,-0.2から0.2までのSEのヒストグラムを描画しよう.
Earnings Interval,\(y\)軸のラベルはFrequencyとする.SEのヒストグラムの描画geom_vline()関数は,vertical(垂直)に直線を引く.xintercept引数で値を指定し,またlinetype引数で適当な線種を指定する(dashedの他にも,dottedやsolidなど多様にオプションが用意されている).PNG形式で出力目標
figuresフォルダにfigure_1.pngの名前を付して出力しよう.ggsave()関数を利用する.第一引数にはファイル名を指定しよう.figuresフォルダのある階層を意識して第一引数を指定しよう.SEが正で少なくとも過去1期は損失回避できた企業群だけに絞り,同様のヒストグラムを描画する方法を実践していこう.Exercise
mutate()関数とlag()関数を組み合わせて,一期前のSEを表すlagged_SEをデータフレームanalysis_sampleに追加しよう.
lag()関数を使う場合は,必ずgroup_by(firm_ID)で企業ごとにグループ化してから適用すること.グループ化せずにlag()を使うと,異なる企業の前行の値を取得してしまう.if_else()関数を用いてyearとlag(year)との関係を示す条件式を予め指定し,lagged_SEの計算式を工夫するのが理想的である.lagged_SE列が追加できれば,前年度損失回避企業をfilter()関数により抽出し,パイプ演算子を使って抽出データをggplot()関数に引き渡して一気にヒストグラムの可視化まで行ってみよう.financial_data,stock_data,およびanalysis_sampleをそのまま使用する.set.seed()関数の引数には,自分の学籍番号の末尾4桁の数字(末尾の英字を除く)を入力すること.# 自分の学籍番号の末尾4桁の数字を入力(例: 学籍番号が2001234Bの場合は1234)
set.seed(1234)
# 自分だけの分析条件を生成
my_year <- sample(2010:2018, 1) # 分析対象の年度
my_breaks <- sample(c(0.002, 0.005, 0.008, 0.01), 1) # ヒストグラムのビン幅
my_threshold <- round(runif(1, min = 0.01, max = 0.05), 3) # サブサンプルの閾値
cat("対象年度:", my_year, "\n")
cat("ビン幅:", my_breaks, "\n")
cat("閾値:", my_threshold, "\n")inner_join() と full_join() の違い問題
financial_dataとstock_dataを,inner_join()で結合した場合とfull_join()で結合した場合のそれぞれについて,nrow()で行数を報告せよ.summarize() + across() による記述統計の作成問題
analysis_sampleから,準備で生成したmy_year年度のデータのみをfilter()で抽出せよ.summarize()で計算し,across(where(is.double), ~ round(.x, 3))で小数点第3位まで丸めよ.my_year年度の\(\text{Mean}\)の値を報告せよ.geom_histogram() + geom_vline() によるヒストグラム問題
analysis_sampleの\(SE\)について,\(-0.2\)から\(0.2\)の範囲で,準備で生成したmy_breaksをビン幅とするヒストグラムをgeom_histogram()で描画せよ.\(x\)軸ラベルはEarnings Interval,\(y\)軸ラベルはFrequencyとすること.geom_vline()を使って\(x = 0\)に破線を追加せよ.my_breaksとでヒストグラムの見え方がどう異なるか,一文で答えよ.問題
analysis_sampleに対し,group_by(firm_ID)の上でlag()とif_else()を用いて前年度の\(SE\)を表すlagged_SE列を追加せよ(講義の練習問題と同様に,yearとlag(year)の差が1であることを確認すること).lagged_SEが準備で生成したmy_threshold以上の企業(\(=\) 前年度に少なくともmy_threshold以上の利益を確保していた企業)のみをfilter()で抽出し,\(SE\)のヒストグラムを描画せよ.ビン幅は\(0.005\),範囲は\(-0.2\)から\(0.2\)とする.(ヒント!)
lagged_SEの作成には,mutate(lagged_SE = if_else(year - lag(year) == 1, lag(SE), NA))のようにif_else()で年度の連続性を確認するのがポイントである.2025 経営データ分析(会計)