16  財務分析のための前処理

この章では、よく財務分析の教科書に登場する財務比率(financial ratio)の使い方や計算方法について説明します。 財務比率は、企業の財務状態を把握するための指標であり、企業の経営者や投資家、債権者、株主などが企業の財務状態を判断するために利用します。

財務比率を計算して、作図や作表するまでのプロセスはざっくり以下の通りです。

  1. read_csv()でデータを読み込む。
  2. dplyr::rename()で変数名を変更する。
  3. str()で変数の型を確認し、カテゴリー変数をfactor()とかas.factor()で因子型に変換する。
  4. 欠損値にゼロを代入するか、その行を除去するかの方針を定めて、dplyr::filter()でデータを抽出したり、dplyr::drop_na()で欠損値を除去したりする。
  5. 欠損値のないデータセットができたら、dplyr::group_by()と一緒にdplyr::summarise()dplyr::mutate()を使って財務比率を計算する。
  6. 計算した財務比率をggplot2で作図したり、kableExtraで表を作成する。

財務比率は、企業の財務諸表項目の分数で表されるため、group_by()関数やmutate()関数を使うことで計算していきます。

必要なパッケージを読み込んでおきます。

この章で分析対象とする企業は,

とします。

この章で用いる会計項目は,

です。 日経NEEDS社会科学情報検索システムでデータを集めるときは,以下の項目コードを使ってください。

R001,R018,R022,B022,B023,B033,B034,B063,B051,B084,B087,B110,C082,C085,C087,C092,C097,C098,D021,D029,D024,D031,D042,D062,D110,D047,D101,D103,K075,K079,H021

16.0.1 データの読み込みと前処理

まずは分析するためのデータを読み込みます。 getwd()setwd()を使って、CSVファイルが入っているフォルダが作業ディレクトリ(working directory)になっているかどうか確認・設定しておきましょう。

注意

日経NEEDS社会科学情報検索システムからダウンロードしたデータは,文字コードがShift-JISであるため,UTF-8を基本とするMacだとread_csv関数でそのまま読み込むと文字化けします。 そのため,read_csv関数のlocale引数でlocale(encoding = "Shift_JIS")を指定して読み込む必要があります。 Shift_JISのところは,cp932sjisでも大丈夫です。

df <- read_csv("data/TSE_2010_EMP500.csv")
Rows: 27174 Columns: 18
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr  (3): 日経会社コード, 企業名称, 決算期
dbl (15): 決算種別, 連結基準, 期末従業員数, 決算月数, 上場場部:コード, 日経業種:コード, 資産合計, 有形固定資産, 【販管費】人...

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

read_csv関数でデータを読み込むと, “Use spec() to retrieve the full column specification for this data.” “Specify the column types or set show_col_types = FALSE to quiet this message.” というメッセージが出ます。 読み込んだデータの完全な仕様(specification)をみたいならspec()関数を使ってね。このメッセージを消したいなら,列のタイプを指定するか,show_col_types = FALSEを指定してね。ということです。無視して大丈夫です。

日経NEEDSからダウンロードしたデータの変数名は、親会社株主に帰属する当期純利益(連結)/当期利益(単独)[累計]のように長いものがあるので, 分析しやすいように分かりやすい変数名に変更します。 変数名は半角英数の単語をアンダーバーでつなげたスネークケース(snake case)で書くことが推奨されます。

たとえば,total_assetnum_employeeのように,変数名から中身が想像できる名前にすることが望ましいです。 一時的につかう変数であれば,xとかgでもよいですが,分析結果を他の人に見せるときは,分かりやすい変数名に変更することが望ましいです。 データフレームなら,df_hoge,テーブルならtbl_hoge,行列ならmat_hogeなど,変数名の先頭にデータ型を示す接頭辞をつけておくことも推奨されます。

# renameで変数名を変更
df <- df |>
  rename(
    nikkei_code = "日経会社コード",
    name = "企業名称",
    date = "決算期",
    kessan = "決算種別",
    renketsu = "連結基準",
    num_employee = "期末従業員数",
    kessan_month = "決算月数",
    listed_code = "上場場部:コード",
    industry_code = "日経業種:コード",
    total_asset = "資産合計",
    tangibles =  "有形固定資産",
    salary =  "【販管費】人件費・福利厚生費[累計]",
    rent_fee = "【販管費】賃借料[累計]",
    corporate_tax = "法人税等[累計]",
    tax_adjustment = "法人税等調整額/繰延税金費用[累計]",
    net_income =   "親会社株主に帰属する当期純利益(連結)/当期利益(単独)[累計]",
    interest_expense = "支払利息・割引料[累計]",
    sales = "売上高・営業収益[累計]"
  )

データが読み込めたら、まずはhead()関数やsummary()関数でデータの中身を確認します。

head(df)
nikkei_code name date kessan renketsu num_employee kessan_month listed_code industry_code total_asset tangibles salary rent_fee corporate_tax tax_adjustment net_income interest_expense sales
0000001 極洋 2010/03 10 1 2909 12 11 235341 64301 11568 3955 NA 923 -281 1086 364 145778
0000001 極洋 2011/03 10 1 2753 12 11 235341 76925 12331 4261 NA 799 -396 58 380 162731
0000001 極洋 2012/03 10 1 2460 12 11 235341 84937 11574 4476 NA 1383 -62 423 419 181885
0000001 極洋 2013/03 10 1 2397 12 11 235341 83245 11281 4571 NA 1139 -441 1269 376 178046
0000001 極洋 2014/03 10 1 2111 12 11 235341 84319 10597 4466 NA 1255 284 2968 385 202387
0000001 極洋 2015/03 10 1 2169 12 11 235341 88937 12241 4628 NA 2389 1216 2433 408 218350
 nikkei_code            name               date               kessan  
 Length:27174       Length:27174       Length:27174       Min.   :10  
 Class :character   Class :character   Class :character   1st Qu.:10  
 Mode  :character   Mode  :character   Mode  :character   Median :10  
                                                          Mean   :10  
                                                          3rd Qu.:10  
                                                          Max.   :10  
                                                                      
    renketsu      num_employee     kessan_month    listed_code   
 Min.   :0.000   Min.   :     0   Min.   : 1.00   Min.   :11.00  
 1st Qu.:1.000   1st Qu.:   795   1st Qu.:12.00   1st Qu.:11.00  
 Median :1.000   Median :  1614   Median :12.00   Median :11.00  
 Mean   :1.083   Mean   :  7229   Mean   :11.98   Mean   :11.28  
 3rd Qu.:1.000   3rd Qu.:  4689   3rd Qu.:12.00   3rd Qu.:12.00  
 Max.   :3.000   Max.   :384586   Max.   :16.00   Max.   :13.00  
                 NA's   :4                                       
 industry_code     total_asset          tangibles            salary       
 Min.   :101001   Min.   :       71   Min.   :       1   Min.   :      1  
 1st Qu.:121204   1st Qu.:    27800   1st Qu.:    5695   1st Qu.:   1719  
 Median :241402   Median :    67269   Median :   16666   Median :   3948  
 Mean   :188818   Mean   :   576964   Mean   :  133755   Mean   :  15426  
 3rd Qu.:257561   3rd Qu.:   206024   3rd Qu.:   57395   3rd Qu.:  11074  
 Max.   :271704   Max.   :303846980   Max.   :13032389   Max.   :1316554  
                  NA's   :3           NA's   :18         NA's   :862      
    rent_fee      corporate_tax     tax_adjustment         net_income      
 Min.   :     1   Min.   :-853182   Min.   :-1120216.0   Min.   :-2008074  
 1st Qu.:   318   1st Qu.:    376   1st Qu.:    -154.0   1st Qu.:     560  
 Median :  1058   Median :   1135   Median :      -5.0   Median :    1984  
 Mean   :  5787   Mean   :   6800   Mean   :     -37.7   Mean   :   13123  
 3rd Qu.:  4270   3rd Qu.:   3657   3rd Qu.:     146.0   3rd Qu.:    6853  
 Max.   :444569   Max.   :1303168   Max.   : 1097414.0   Max.   : 4987962  
 NA's   :18853    NA's   :25        NA's   :420          NA's   :6         
 interest_expense     sales         
 Min.   :    -6   Min.   :       3  
 1st Qu.:    30   1st Qu.:   27268  
 Median :   112   Median :   67179  
 Mean   :  1563   Mean   :  330903  
 3rd Qu.:   457   3rd Qu.:  206892  
 Max.   :555902   Max.   :37154298  
 NA's   :1989     NA's   :11        

summary()の出力を見ると,各変数の記述統計量と欠損値NAの個数が表示されています。 賃借料rent_feeと支払利息interest_expenseの欠損値が比較的多いように見えますが,これは企業が支払っている賃借料や支払利息が小さく,損益計算書に記載されていないだけなので,ここではゼロを代入するようにします。

(連結)財務諸表では,金額の小さな項目を「その他」にまとめて記載するため,金額が小さい個別の項目はデータ上欠損値になりますが,欠損しているわけではなく,金額が小さいだけなので,ここではゼロを代入しています。

NAにゼロを代入するには,is.na()関数を使います。 is.na()関数はNATRUEを返す関数で,これをつかってTRUEとなる値にゼロを代入する処理を行います。

たとえば,次のようなベクトルxNAが含まれているかどうかを調べてみます。

x <- c(1,2,NA,4,5)
is.na(x)
[1] FALSE FALSE  TRUE FALSE FALSE

すると,FALSE FALSE TRUE FALSE FALSEと表示され,3番目の要素がNAであることが分かります。ここに3を代入するには,次のようにします。

x[is.na(x)] <- 3
x
[1] 1 2 3 4 5

x[is.na(x)]とすると,xの中でNAの要素を取り出すことができ,そこに3を代入しています。

df$rent_fee[is.na(df$rent_fee)] <- 0
df$interest_expense[is.na(df$interest_expense)] <- 0

それ以外にも欠損値をもつ項目はありますが,売上高や当期純利益が欠損値となっているのは異常なので,そういった行は後でfilter()関数で除外します。 データの構造をglimpse()関数で再確認します。

glimpse(df)
Rows: 27,174
Columns: 18
$ nikkei_code      <chr> "0000001", "0000001", "0000001", "0000001", "0000001"…
$ name             <chr> "極洋", "極洋", "極洋", "極洋", "極洋", "極洋", "極洋…
$ date             <chr> "2010/03", "2011/03", "2012/03", "2013/03", "2014/03"…
$ kessan           <dbl> 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 1…
$ renketsu         <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,…
$ num_employee     <dbl> 2909, 2753, 2460, 2397, 2111, 2169, 2249, 2193, 2257,…
$ kessan_month     <dbl> 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 1…
$ listed_code      <dbl> 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 1…
$ industry_code    <dbl> 235341, 235341, 235341, 235341, 235341, 235341, 23534…
$ total_asset      <dbl> 64301, 76925, 84937, 83245, 84319, 88937, 94608, 9739…
$ tangibles        <dbl> 11568, 12331, 11574, 11281, 10597, 12241, 16972, 1713…
$ salary           <dbl> 3955, 4261, 4476, 4571, 4466, 4628, 4704, 4926, 5089,…
$ rent_fee         <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2508, 2669,…
$ corporate_tax    <dbl> 923, 799, 1383, 1139, 1255, 2389, 804, 1518, 1416, 12…
$ tax_adjustment   <dbl> -281, -396, -62, -441, 284, 1216, -235, 58, -58, 251,…
$ net_income       <dbl> 1086, 58, 423, 1269, 2968, 2433, 1799, 2422, 3211, 29…
$ interest_expense <dbl> 364, 380, 419, 376, 385, 408, 437, 418, 433, 443, 446…
$ sales            <dbl> 145778, 162731, 181885, 178046, 202387, 218350, 22662…

日経コードnikkei_codeと企業名称name、決算期dateの3つは文字列<chr>で、それ以外の変数は数値<dbl>となっています。 しかし、実際は、kessanrenketsulisted_codeindustry_codeはカテゴリカルデータであるため、factor型に変換します。

df <- df |>
  mutate(
    kessan = as.factor(kessan),
    renketsu = as.factor(renketsu),
    listed_code = as.factor(listed_code),
    industry_code = as.factor(industry_code) # ファクター
  )

また財務比率は分数で計算されるため、分母がゼロあるいはゼロに近い値をもつと、計算ができなかったり、異常に大きい値が出てきたりします。 そのため、分母となる変数にゼロが含まないようにし、また異常値を除外します。 実証研究では、連続変数に対して上下1%以上の異常値を除外することが多いです。

df <- df |> # 売上高、有形固定資産、従業員数が0の企業を除外
  filter(sales > 0 & tangibles > 0 & num_employee > 0) |>
  drop_na() # それ以外の欠損値をもつ行を削除

最後にデータを確認してみます。

 nikkei_code            name               date           kessan     renketsu 
 Length:25895       Length:25895       Length:25895       10:25895   0:  986  
 Class :character   Class :character   Class :character              1:23815  
 Mode  :character   Mode  :character   Mode  :character              2:   39  
                                                                     3: 1055  
                                                                              
                                                                              
                                                                              
  num_employee     kessan_month   listed_code industry_code  
 Min.   :    12   Min.   : 3.00   11:18782    271704 : 5017  
 1st Qu.:   792   1st Qu.:12.00   12: 6851    245444 : 1375  
 Median :  1566   Median :12.00   13:  262    121210 :  870  
 Mean   :  5602   Mean   :11.98               127262 :  668  
 3rd Qu.:  4358   3rd Qu.:12.00               123225 :  666  
 Max.   :289191   Max.   :16.00               107071 :  612  
                                              (Other):16687  
  total_asset         tangibles           salary           rent_fee       
 Min.   :     231   Min.   :      1   Min.   :      1   Min.   :     0.0  
 1st Qu.:   27830   1st Qu.:   5706   1st Qu.:   1754   1st Qu.:     0.0  
 Median :   65214   Median :  16148   Median :   4012   Median :     0.0  
 Mean   :  341095   Mean   :  97151   Mean   :  15602   Mean   :  1825.2  
 3rd Qu.:  187788   3rd Qu.:  51560   3rd Qu.:  11214   3rd Qu.:   251.5  
 Max.   :82187392   Max.   :7214561   Max.   :1316554   Max.   :444569.0  
                                                                          
 corporate_tax     tax_adjustment         net_income       interest_expense  
 Min.   :-139945   Min.   :-206722.00   Min.   :-2008074   Min.   :    -6.0  
 1st Qu.:    381   1st Qu.:   -145.00   1st Qu.:     569   1st Qu.:    19.0  
 Median :   1107   Median :     -5.00   Median :    1945   Median :    89.0  
 Mean   :   5022   Mean   :    -46.04   Mean   :    9414   Mean   :   988.9  
 3rd Qu.:   3380   3rd Qu.:    139.00   3rd Qu.:    6386   3rd Qu.:   359.0  
 Max.   : 970546   Max.   : 115523.00   Max.   : 1180694   Max.   :117310.0  
                                                                             
     sales         
 Min.   :     228  
 1st Qu.:   27361  
 Median :   64862  
 Mean   :  253626  
 3rd Qu.:  189714  
 Max.   :21571973  
                   

これで前処理が終わったdfを保存しておきましょう。

write_csv(df, "data/productivity.csv")