---
title: "4 財務データの加工,集計,及び可視化"
date: 2026/05/01
format:
html: default
revealjs:
output-file: 4_data_slide.html
---
## 財務データの読み込み(教科書第4.2節)
### `readr`の`read_csv()`関数を用いたデータの読み込み
```{r}
# tidyverseの読み込み
pacman::p_load(tidyverse)
# これまではread.csv()関数,これからはreadrのread_csv()関数を使う
financial_data <- read_csv("ch04_financial_data.csv")
# 行数の確認
nrow(financial_data)
# 冒頭N行を確認するにはhead(financial_data, N)とする
head(financial_data)
```
------------------------------------------------------------------------
### `read_csv()`関数の特徴
1. データの読み込みがより高速であり,かつ,型推論が柔軟である.
2. 読み込んだデータをデータフレームではなく,その改良版である`tibble`で返す.
- データフレームには,列名の空白を勝手に`.`(ピリオド)に変換したり,うっかり`print()`関数で表示すると膨大な行数全てを表示してしまったりと,様々な不都合な側面があり,`tibble`はそれらを改良したものである[^1].
3. 列名を勝手に(`X.1`, `X.2`, `X.3`などのように)変換しない.
4. 文字列を勝手にファクター型扱いしない.
------------------------------------------------------------------------
### `read_csv()`関数の型推論の柔軟性
```{r}
daily_stock_return <- read.csv("ch03_daily_stock_return.csv")
str(daily_stock_return)
daily_stock_return <- read_csv("ch03_daily_stock_return.csv")
str(daily_stock_return)
```
- `read_csv()`関数で読み込んだ`date`列が[**日付型 (`Date`)**]{style="color: red"}になっていることが確認できる.他方,基本パッケージの`read.csv()`関数で読み込むと,この列は文字型 (`chr`)と認識されていたので,`read_csv()`関数の方がより正確に型推論できていることが分かる.
------------------------------------------------------------------------
### ファクター型への変換
```{r}
# class()関数を用いて,各変数の型を確認しよう
class(financial_data$firm_ID)
class(financial_data$industry_ID)
```
- `firm_ID`列と`industry_ID`列は,いずれもカテゴリカル変数にも関わらず,数値型 (`numeric`)になっている.
- そこで,`as.factor()`関数を使ってきちんとファクター型に変換しておこう.
------------------------------------------------------------------------
### (続)ファクター型への変換
```{r}
# 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_ID`と`industry_ID`の下にある`<fct>`は,`factor`(ファクター)型を意味する.それ以外の列の`<dbl>`は`double`(倍精度浮動小数点数)型を意味し,実数を表すのに用いられる数値型の一種である.
------------------------------------------------------------------------
## 探索的データ分析(教科書第4.3節)
### データセットの概要確認
- 初見のデータセットを扱う場合,データ分析を本格的に始める前にまずはその概要を大まかに掴む必要がある.その作業を一般に[**探索的データ分析**]{style="color: blue"} (exploratory data analysis)と言い,データの特徴や構造を理解することを目的とする.
- 一口に探索的データ分析と言っても,データの性質に応じて様々な方法が考えられるが,まずは手始めに`summary()`関数を用いてみよう.
------------------------------------------------------------------------
### (続)データセットの概要確認
```{r}
# 要約統計量の表示
summary(financial_data)
```
- `summary()`関数は,数値型(整数型や倍精度浮動小数点数型)が代入された場合,各データセットに含まれる各変数の平均や中央値,分位点を返す.
- ファクター型に対しては,要素数が多いカテゴリーを上から順に表示する.
------------------------------------------------------------------------
### 欠損データの処理
```{r}
# head()関数を用いて冒頭6行の結果のみ表示
head(complete.cases(financial_data))
```
- ここで登場した`TRUE`と`FALSE`は,通称論理型 (`logical`)と呼ばれるデータ型である.その特徴は,`TRUE`と`FALSE`の二つのみで構成される点にある.この二つを算術関数の引数として用いると,`TRUE`が1,`FALSE`が0と解釈されるので,`sum()`関数の引数に`complete.cases(financial_data)`を代入することで,欠損が無い観測値数を数え上げてくれる.
```{r}
# 欠損のない行の総数をカウント
sum(complete.cases(financial_data)) # TRUE/FALSEを1/0に変換して足し合わせる
```
------------------------------------------------------------------------
### (続)欠損データの処理
- 欠損データの処理について,最も単純な方法は,欠損値が含まれる観測データを削除してしまうことである.
- `tidyr`に含まれる`drop_na()`関数は,第二引数を省略した場合,入力されたデータフレームに対し,欠損値が存在しない行のみを抽出して返す.
```{r}
# 元々のデータフレームを確認
head(financial_data)
# 欠損行を削除し,データフレームを上書き
financial_data <- drop_na(financial_data)
# 欠損行を削除後のデータフレームを確認
head(financial_data)
```
------------------------------------------------------------------------
## データの加工から可視化まで(教科書第4.4節)
### `dplyr`のパイプ演算子の使い方
::: {.callout-note icon="false"}
#### 目標
- 2015 年度のデータのみを抽出して,売上高の自然対数をヒストグラムで描画してみよう.
:::
::::: columns
::: {.column width="35%"}
{fig-align="center"}
:::
::: {.column width="65%"}
{fig-align="center"}
:::
:::::
- パイプ演算子`%>%`は,**左側で処理されたデータフレームを,右側の関数の第一引数として受け渡す**役割を果たす.
------------------------------------------------------------------------
### 実際の使用例
- パイプ演算子`%>%`の入力は,Rstudio上で以下のショートカットキーを利用すると便利である.
- Macの場合: ⌘ + Shift + m
- Windowsの場合: Ctrl + Shift + m
```{r}
# 2015年度のデータのみ抽出
financial_data %>%
filter(year == 2015) # 2015年度のみ抽出
```
------------------------------------------------------------------------
### 抽出後,更に列選択して別名で保存
- 抽出後に`firm_ID`,`year`,`sales`の三列を選択し,こうして出来上がった新たなデータフレームを`financial_data_2015`として定義しよう.
```{r}
# 抽出後,列選択し,新たなデータフレームとして定義
financial_data_2015 <- financial_data %>%
filter(year == 2015) %>% # 2015年度のみ抽出
select(firm_ID, year, sales) # 必要な列のみ選択
head(financial_data_2015) # head()関数で確認
```
------------------------------------------------------------------------
### 2015年度のデータを抽出して一気に可視化まで処理
- わざわざ`financial_data_2015`を作らなくても,目標を達成するだけであれば,`filter()`関数を適用した後のデータを`ggplot()`関数に引き渡してあげれば良い.
```{r}
financial_data %>%
filter(year == 2015) %>%
ggplot() # %>%演算子以前のデータを第一引数に取るので()内の指定不要
```
------------------------------------------------------------------------
### ヒストグラムを描画し,体裁を整える {#ヒストグラムを描画し体裁を整える}
```{r}
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$軸にぴったりくっ付くよう調整する役割を果たす.
------------------------------------------------------------------------
## `mutate()`関数を使って新たな列の追加(教科書第4.6節)
### 会計上の株主のリターン $=$ ROE
{width="80%"}
------------------------------------------------------------------------
### 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は,一期間における[**会計上の株主のリターン**]{style="color: red"}を表す.
------------------------------------------------------------------------
### ここでの目標
::: {.callout-note icon="false"}
#### 目標
- [**目標1:**]{style="color: blue"} `financial_data`に$t$期末の株主資本`BE`列を追加する.
- [**目標2:**]{style="color: blue"} 次に,`financial_data`に$t-1$期末の株主資本を表す`lagged_BE`列を追加する.
- [**目標3:**]{style="color: blue"} `financial_data`に`ROE`列を追加
- [**目標4:**]{style="color: blue"} こうして計算された`ROE`をヒストグラムに可視化する.ただし,作図に利用するのは,`ROE`が-0.2から0.4の観測値のみ,ビン幅は0.01に指定すること.また,$x$軸のラベルは`ROE Interval`,$y$軸のラベルは`Frequency`とすること.
:::
------------------------------------------------------------------------
### 目標1: `BE`列の追加
```{r}
# mutate()関数を用いて株主資本BE列の追加
financial_data <- financial_data %>%
mutate(BE = (OA + FA) - (OL + FO)) # 資産合計から負債合計を差し引いて計算
```
- `dplyr`では新しい列を追加するのに[**`mutate()`関数**]{style="color: red"}を用いる.
{width="80%"}
------------------------------------------------------------------------
### 目標2: `lagged_BE`列の追加
```{r}
# lag()関数を用いて1年前の株主資本lagged_BE列を追加
financial_data <- financial_data %>%
group_by(firm_ID) %>% # ①firm_IDでグループ化
mutate(lagged_BE = lag(BE)) %>% # ②lag()関数を使ってlagged_BEを追加
ungroup()
```
{width="60%"}
------------------------------------------------------------------------
### 先のコードの概要
:::::: small
::::: columns
::: {.column width="50%"}

:::
::: {.column width="50%"}
- [**2行目:**]{style="color: blue"} 以下の処理により作成されるデータフレームを`financial_data`に上書き.
- [**3行目:**]{style="color: blue"} `group_by()`関数を用いて,`firm_ID`に基づく[**グループ化情報を付与**]{style="color: red"}.
- [**4行目:**]{style="color: blue"} `mutate()`関数内で`lag()`関数を使うことで,`lagged_BE`列を作成し,そこに一期前の`BE`を格納.
- [**5行目:**]{style="color: blue"} `ungroup()`関数を用い,[**不要になったグループ化情報を消去**]{style="color: red"}.これを忘れると,変数にグループ化情報が付与されたままになって,その後の処理も意図せずグループごとに行われてしまうので注意しよう.
:::
:::::
::::::
------------------------------------------------------------------------
### 目標3: `ROE`列を追加
- 最後に`mutate()`関数を使って,`ROE`列を追加しよう.
```{r}
# ROE列の追加
financial_data <- financial_data %>%
mutate(ROE = X / lagged_BE) # 定義に従ってROEを計算
```
{width="60%"}
------------------------------------------------------------------------
### 実践上はパイプ演算子を繋げて書く
```{r}
# 実践での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列の追加
```
{width="60%"}
------------------------------------------------------------------------
### 目標4: `ROE`のヒストグラム
- 最終目標として,`ggplot2`を利用し,`ROE`をヒストグラムにより描画しよう.
```{r}
# 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()`関数は等差数列を作成するための関数であり,[**第一引数に始点,第二引数に終点,第三引数に等差数列の差分**]{style="color: blue"}を取る[(教科書84頁)]{style="color: purple"}.
- ここでは-0.2から0.4までの`ROE`を描画することを考え,ビン幅に相当する等差数列の差分は0.01としてみよう.
------------------------------------------------------------------------
## 集計作業(教科書第4.7.1節の応用)
### `summarize`関数の使い方 {#drop_na}
::: {.callout-note icon="false"}
#### 目標
- ROEが計算可能な観測値のみを抽出し,年度ごとにROEの平均値を求めよ.
:::
```{r}
# 年度ごとにROEの平均値を算出
financial_data %>%
drop_na(ROE) %>% # ROEが欠損値の観測値を削除
group_by(year) %>% # 年でグループ化
summarize(mean_ROE = mean(ROE)) # 各年のROEの平均値mean_ROEを計算
```
### 先のコードの概要
- [**3行目:**]{style="color: blue"} `tidyr`に含まれる`drop_na()`関数は,第二引数で指定した変数(この場合であれば`ROE`列)に欠損値が存在しない行のみを抽出して返す[(教科書152頁)]{style="color: purple"}.
- [**4行目:**]{style="color: blue"} `group_by()`関数を用いて,年度`year`に基づいてグループ化.
- [**5行目:**]{style="color: blue"} そして`summarize()`関数を用いて,各グループ(年度)ごとに平均ROEを計算し,`mean_ROE`列に保存する.
- (注意点)`summarize()`関数を適用することにより,グループ化は解除されるため,`ungroup()`の追加は不要である.ただし,`summarize()`関数は1つのグループしか解除しないため,複数の変数でグループ化した場合は,最後に`ungroup()`関数を挿入する必要がある.
### 平均値計算から可視化までを一度に処理
```{r}
# 年度ごとに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() # グラフ全体の体裁を設定
```
------------------------------------------------------------------------
### 練習問題
::: {.callout-note icon="false"}
#### Exercise 1
- `firm_ID`が`350`の企業の売上高を折れ線グラフで表示せよ.ただし,$y$軸は売上高`sales`,$x$軸は年度`year` を取ることとする.
:::
::: {.callout-note icon="false"}
#### Exercise 2
- 最終年度のROEに関して20%分位点を求め,`ROE_first_quintile`という変数に保存せよ.
- **(ヒント)** 分位点を求めるには`quantile()`関数を用いる.この関数は第一引数にデータセット,第二引数に求めたい分位点の値をパーセントでなく小数表示で代入する.また,データセットに欠損値が含まれている場合,`na.rm = TRUE` を追加する必要がある.`na.rm`はremove NA values の略を意味する.
- 最終年度の ROEが`ROE_first_quintile`より小さい企業は何社あるか答えよ.ただし,ROEが欠損している企業はカウントしないこと.
:::
[^1]: 実際のデータ分析ではデータフレームと`tibble`の区別を意識する場面は少なく,教科書でも特に必要がない場合は両者を区別せずにデータフレームと呼んでいる.