4 財務データの加工,集計,及び可視化

Published

2024/05/01

Modified

2024/06/27

1 財務データの読み込み(教科書第4.2節)

1.1 readrread_csv()関数を用いたデータの読み込み

Code
# tidyverseの読み込み
pacman::p_load(tidyverse) 

# これまではread.csv()関数,これからはreadrのread_csv()関数を使う
financial_data <- read_csv("ch04_financial_data.csv") 

# 行数の確認
nrow(financial_data) 
[1] 7920
Code
# 冒頭N行を確認するにはhead(financial_data, N)とする
head(financial_data) 

1.2 read_csv()関数の特徴

  1. データの読み込みがより高速であり,かつ,型推論が柔軟である.
  2. 読み込んだデータをデータフレームではなく,その改良版であるtibbleで返す.
  • データフレームには,列名の空白を勝手に.(ピリオド)に変換したり,うっかりprint()関数で表示すると膨大な行数全てを表示してしまったりと,様々な不都合な側面があり,tibbleはそれらを改良したものである1
  1. 列名を勝手に(X.1, X.2, X.3などのように)変換しない.
  2. 文字列を勝手にファクター型扱いしない.

1.3 read_csv()関数の型推論の柔軟性

Code
daily_stock_return  <- read.csv("ch03_daily_stock_return.csv") 
str(daily_stock_return)
'data.frame':   21 obs. of  3 variables:
 $ date : chr  "2020-04-01" "2020-04-02" "2020-04-03" "2020-04-06" ...
 $ firm1: num  -0.03948 0.00598 0.05579 0.04193 -0.02019 ...
 $ firm2: num  0.07696 -0.00725 -0.0173 0.00217 0.07555 ...
Code
daily_stock_return  <- read_csv("ch03_daily_stock_return.csv") 
str(daily_stock_return)
spc_tbl_ [21 × 3] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ date : Date[1:21], format: "2020-04-01" "2020-04-02" ...
 $ firm1: num [1:21] -0.03948 0.00598 0.05579 0.04193 -0.02019 ...
 $ firm2: num [1:21] 0.07696 -0.00725 -0.0173 0.00217 0.07555 ...
 - attr(*, "spec")=
  .. cols(
  ..   date = col_date(format = ""),
  ..   firm1 = col_double(),
  ..   firm2 = col_double()
  .. )
 - attr(*, "problems")=<externalptr> 
  • read_csv()関数で読み込んだdate列が日付型 (Date)になっていることが確認できる.他方,基本パッケージのread.csv()関数で読み込むと,この列は文字型 (chr)と認識されていたので,read_csv()関数の方がより正確に型推論できていることが分かる.

1.4 ファクター型への変換

Code
# class()関数を用いて,各変数の型を確認しよう
class(financial_data$firm_ID)
[1] "numeric"
Code
class(financial_data$industry_ID)
[1] "numeric"
  • firm_ID列とindustry_ID列は,いずれもカテゴリカル変数にも関わらず,数値型 (numeric)になっている.
  • そこで,as.factor()関数を使ってきちんとファクター型に変換しておこう.

1.5 (続)ファクター型への変換

Code
# firm_ID列とindustry_ID列をファクター型に変換
financial_data$firm_ID <- as.factor(financial_data$firm_ID)
financial_data$industry_ID <- as.factor(financial_data$industry_ID)

head(financial_data)
  • # A tibble:6 x 11以下を見てみると,各変数の下にはそれぞれの変数のデータ型が記述されており,firm_IDindustry_IDの下にある<fct>は,factor(ファクター)型を意味する.それ以外の列の<dbl>double(倍精度浮動小数点数)型を意味し,実数を表すのに用いられる数値型の一種である.

2 探索的データ分析(教科書第4.3節)

2.1 データセットの概要確認

  • 初見のデータセットを扱う場合,データ分析を本格的に始める前にまずはその概要を大まかに掴む必要がある.その作業を一般に探索的データ分析 (exploratory data analysis)と言い,データの特徴や構造を理解することを目的とする.
  • 一口に探索的データ分析と言っても,データの性質に応じて様々な方法が考えられるが,まずは手始めにsummary()関数を用いてみよう.

2.2 (続)データセットの概要確認

Code
# 要約統計量の表示
summary(financial_data)
      year         firm_ID      industry_ID       sales        
 Min.   :2015   1      :   6   3      :1760   Min.   :    205  
 1st Qu.:2016   2      :   6   10     :1702   1st Qu.:  16103  
 Median :2018   3      :   6   7      :1334   Median :  40431  
 Mean   :2018   4      :   6   1      :1143   Mean   : 166007  
 3rd Qu.:2019   5      :   6   9      : 667   3rd Qu.: 118314  
 Max.   :2020   7      :   6   8      : 429   Max.   :3496433  
                (Other):7884   (Other): 885                    
       OX                 NFE                  X                   OA         
 Min.   :-353606.7   Min.   :-285383.9   Min.   :-357624.8   Min.   :    217  
 1st Qu.:    399.3   1st Qu.:    -66.4   1st Qu.:    383.3   1st Qu.:  12560  
 Median :   1602.9   Median :     -1.2   Median :   1586.1   Median :  30799  
 Mean   :   7968.9   Mean   :     64.0   Mean   :   7904.9   Mean   : 152273  
 3rd Qu.:   5260.5   3rd Qu.:     41.4   3rd Qu.:   5204.6   3rd Qu.:  93469  
 Max.   : 398034.5   Max.   : 331035.3   Max.   : 572588.7   Max.   :7987936  
                     NA's   :1                                                
       FA                 OL                FO         
 Min.   :     288   Min.   :     35   Min.   :     44  
 1st Qu.:    6835   1st Qu.:   3965   1st Qu.:   3757  
 Median :   19095   Median :  10868   Median :  11125  
 Mean   :   80185   Mean   :  50261   Mean   :  70681  
 3rd Qu.:   52118   3rd Qu.:  33111   3rd Qu.:  35446  
 Max.   :29250611   Max.   :2817975   Max.   :7026924  
                                                       
  • summary()関数は,数値型(整数型や倍精度浮動小数点数型)が代入された場合,各データセットに含まれる各変数の平均や中央値,分位点を返す.
  • ファクター型に対しては,要素数が多いカテゴリーを上から順に表示する.

2.3 欠損データの処理

Code
# head()関数を用いて冒頭6行の結果のみ表示
head(complete.cases(financial_data)) 
[1] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
  • ここで登場したTRUEFALSEは,通称論理型 (logical)と呼ばれるデータ型である.その特徴は,TRUEFALSEの二つのみで構成される点にある.この二つを算術関数の引数として用いると,TRUEが1,FALSEが0と解釈されるので,sum()関数の引数にcomplete.cases(financial_data)を代入することで,欠損が無い観測値数を数え上げてくれる.
Code
# 欠損のない行の総数をカウント
sum(complete.cases(financial_data)) # TRUE/FALSEを1/0に変換して足し合わせる
[1] 7919

2.4 (続)欠損データの処理

  • 欠損データの処理について,最も単純な方法は,欠損値が含まれる観測データを削除してしまうことである.
  • tidyrに含まれるdrop_na()関数は,第二引数を省略した場合,入力されたデータフレームに対し,欠損値が存在しない行のみを抽出して返す.
Code
# 元々のデータフレームを確認
head(financial_data) 
Code
# 欠損行を削除し,データフレームを上書き
financial_data <- drop_na(financial_data) 

# 欠損行を削除後のデータフレームを確認
head(financial_data) 

3 データの加工から可視化まで(教科書第4.4節)

3.1 dplyrのパイプ演算子の使い方

目標
  • 2015 年度のデータのみを抽出して,売上高の自然対数をヒストグラムで描画してみよう.

  • パイプ演算子%>%は,左側で処理されたデータフレームを,右側の関数の第一引数として受け渡す役割を果たす.

3.2 実際の使用例

  • パイプ演算子%>%の入力は,Rstudio上で以下のショートカットキーを利用すると便利である.
    • Macの場合: ⌘ + Shift + m
    • Windowsの場合: Ctrl + Shift + m
Code
# 2015年度のデータのみ抽出
financial_data %>% 
  filter(year == 2015) # 2015年度のみ抽出

3.3 抽出後,更に列選択して別名で保存

  • 抽出後にfirm_IDyearsalesの三列を選択し,こうして出来上がった新たなデータフレームをfinancial_data_2015として定義しよう.
Code
# 抽出後,列選択し,新たなデータフレームとして定義
financial_data_2015 <- financial_data %>% 
  filter(year == 2015) %>% # 2015年度のみ抽出 
  select(firm_ID, year, sales) # 必要な列のみ選択

head(financial_data_2015) # head()関数で確認

3.4 2015年度のデータを抽出して一気に可視化まで処理

  • わざわざfinancial_data_2015を作らなくても,目標を達成するだけであれば,filter()関数を適用した後のデータをggplot()関数に引き渡してあげれば良い.
Code
financial_data %>% 
  filter(year == 2015) %>% 
  ggplot() # %>%演算子以前のデータを第一引数に取るので()内の指定不要


3.5 ヒストグラムを描画し,体裁を整える

Code
financial_data %>% 
  filter(year == 2015) %>% 
  ggplot() +
  geom_histogram(aes(x = log(sales))) + # ヒストグラムの描画
  scale_y_continuous(expand = c(0,0)) + # x軸の位置を調整
  theme_classic()

  • ggplot2でヒストグラムを描くには,geom_histogram()関数を用いる.
  • aes()引数には,\(x\)軸の値としてlog(sales)を指定する.
  • scale_y_continuous(expand = c(0,0))はヒストグラムが\(x\)軸にぴったりくっ付くよう調整する役割を果たす.

4 mutate()関数を使って新たな列の追加(教科書第4.6節)

4.1 会計上の株主のリターン \(=\) ROE


4.2 ROEの計算方法

\[ \begin{align} ROE_{t} = \frac{X_{t}}{\mathit{BE}_{t-1}} \label{eq:ch04_ROE} \end{align} \]

  • ここで分子の\(X_{t}\)\(t\)期の当期純利益を指し,分母の\(\mathit{BE}_{t-1}\)\(t\)期首(別の言い方をすると\(t-1\)期末)の株主資本を指す.
  • 分母の\(\mathit{BE}\)は一期前の値を取っていることに注意しよう.
  • これは,ROEを期首時点の株主の投資額(期首の株主資本)に対する期中の投資の成果(期中の当期純利益)と解釈するためである.
  • こうして計算されたROEは,一期間における会計上の株主のリターンを表す.

4.3 ここでの目標

目標
  • 目標1: financial_data\(t\)期末の株主資本BE列を追加する.
  • 目標2: 次に,financial_data\(t-1\)期末の株主資本を表すlagged_BE列を追加する.
  • 目標3: financial_dataROE列を追加
  • 目標4: こうして計算されたROEをヒストグラムに可視化する.ただし,作図に利用するのは,ROEが-0.2から0.4の観測値のみ,ビン幅は0.01に指定すること.また,\(x\)軸のラベルはROE Interval\(y\)軸のラベルはFrequencyとすること.

4.4 目標1: BE列の追加

Code
# mutate()関数を用いて株主資本BE列の追加
financial_data <- financial_data %>%
  mutate(BE = (OA + FA) - (OL + FO)) # 資産合計から負債合計を差し引いて計算
  • dplyrでは新しい列を追加するのにmutate()関数を用いる.


4.5 目標2: lagged_BE列の追加

Code
# lag()関数を用いて1年前の株主資本lagged_BE列を追加
financial_data <- financial_data %>%
  group_by(firm_ID) %>% # ①firm_IDでグループ化
  mutate(lagged_BE = lag(BE)) %>% # ②lag()関数を使ってlagged_BEを追加
  ungroup()


4.6 先のコードの概要

  • 2行目: 以下の処理により作成されるデータフレームをfinancial_dataに上書き.
  • 3行目: group_by()関数を用いて,firm_IDに基づくグループ化情報を付与
  • 4行目: mutate()関数内でlag()関数を使うことで,lagged_BE列を作成し,そこに一期前のBEを格納.
  • 5行目: ungroup()関数を用い,不要になったグループ化情報を消去.これを忘れると,変数にグループ化情報が付与されたままになって,その後の処理も意図せずグループごとに行われてしまうので注意しよう.

4.7 目標3: ROE列を追加

  • 最後にmutate()関数を使って,ROE列を追加しよう.
Code
# ROE列の追加
financial_data <- financial_data %>%
  mutate(ROE = X / lagged_BE) # 定義に従ってROEを計算


4.8 実践上はパイプ演算子を繋げて書く

Code
# 実践でのROEの計算
financial_data <- financial_data %>%
  mutate(BE = (OA + FA) - (OL + FO)) %>%  # 目標1: BE列の追加
  group_by(firm_ID) %>% # 目標2: 以下の三行でlagged_BE列を追加
  mutate(lagged_BE = lag(BE)) %>% 
  ungroup() %>% 
  mutate(ROE = X / lagged_BE) # 目標3: ROE列の追加


4.9 目標4: ROEのヒストグラム

  • 最終目標として,ggplot2を利用し,ROEをヒストグラムにより描画しよう.
Code
# ROEのヒストグラムの描画
ggplot(financial_data) +
  geom_histogram(aes(x = ROE),
                 breaks = seq(-0.2, 0.4, 0.01)) +
  labs(x = "ROE Interval", y = "Frequency") + 
  scale_y_continuous(expand = c(0, 0)) +
  theme_classic()

  • geom_histogram()関数のbreaks引数により\(x\)軸の範囲とビン幅を調整している.
  • seq()関数は等差数列を作成するための関数であり,第一引数に始点,第二引数に終点,第三引数に等差数列の差分を取る(教科書84頁)
  • ここでは-0.2から0.4までのROEを描画することを考え,ビン幅に相当する等差数列の差分は0.01としてみよう.

5 集計作業(教科書第4.7.1節の応用)

5.1 summarize関数の使い方

目標
  • ROEが計算可能な観測値のみを抽出し,年度ごとにROEの平均値を求めよ.
Code
# 年度ごとにROEの平均値を算出
financial_data %>% 
  drop_na(ROE) %>% # ROEが欠損値の観測値を削除
  group_by(year) %>% # 年でグループ化
  summarize(mean_ROE = mean(ROE)) # 各年のROEの平均値mean_ROEを計算

5.2 先のコードの概要

  • 3行目: tidyrに含まれるdrop_na()関数は,第二引数で指定した変数(この場合であればROE列)に欠損値が存在しない行のみを抽出して返す(教科書152頁)
  • 4行目: group_by()関数を用いて,年度yearに基づいてグループ化.
  • 5行目: そしてsummarize()関数を用いて,各グループ(年度)ごとに平均ROEを計算し,mean_ROE列に保存する.
    • (注意点)summarize()関数を適用することにより,グループ化は解除されるため,ungroup()の追加は不要である.ただし,summarize()関数は1つのグループしか解除しないため,複数の変数でグループ化した場合は,最後にungroup()関数を挿入する必要がある.

5.3 平均値計算から可視化までを一度に処理

Code
# 年度ごとにROEの平均値を求め,折れ線グラフにより描画
financial_data %>% 
  drop_na(ROE) %>% 
  group_by(year) %>% 
  summarize(mean_ROE = mean(ROE)) %>%
  ggplot() + # ggplot()関数にデータを引き渡す
  geom_line(aes(x = year, y = mean_ROE)) + 
    # 折れ線グラフを描くにはgeom_line()関数を用いる
  labs(x = "Year", y = "Mean ROE") + # 両軸のラベルを設定
  theme_classic() # グラフ全体の体裁を設定


5.4 練習問題

Exercise 1
  • firm_ID350の企業の売上高を折れ線グラフで表示せよ.ただし,\(y\)軸は売上高sales\(x\)軸は年度year を取ることとする.
Exercise 2
  • 最終年度のROEに関して20%分位点を求め,ROE_first_quintileという変数に保存せよ.
    • (ヒント) 分位点を求めるにはquantile()関数を用いる.この関数は第一引数にデータセット,第二引数に求めたい分位点の値をパーセントでなく小数表示で代入する.また,データセットに欠損値が含まれている場合,na.rm = TRUE を追加する必要がある.na.rmはremove NA values の略を意味する.
  • 最終年度の ROEがROE_first_quintileより小さい企業は何社あるか答えよ.ただし,ROEが欠損している企業はカウントしないこと.

Footnotes

  1. 実際のデータ分析ではデータフレームとtibbleの区別を意識する場面は少なく,教科書でも特に必要がない場合は両者を区別せずにデータフレームと呼んでいる.↩︎