3.3 データの整形

3.3.1 tidyverse の活用

データの整形には、tidyverseパッケージ群に含まれるdplyrというパッケージを用いる。作業では、tidyverseをインストール・起動しておけばdplyrも利用できるため、特に心配する必要はない。dplyr には、いくつもの便利な関数がふくまれているが、本節では主に以下の関数および機能を紹介する。

  1. summarize():
  • データセットを関数内で定義した統計量等を用いて要約された新しいデータセットに変換するための関数
  1. mutate():
  • データセットに新しい変数を追加するための関数
  1. filter():
  • データセットから、関数内で指示する特定のレコード(行)を残す(フィルタリング)するための関数
  1. select():
  • データセットから、関数内で指示する特定の列を抽出するための関数
  1. arrange():
  • データセットから、関数内で指示する順番で並べ替えるための関数
  1. パイプ演算子 %>%:
  • 前(左)の関数の出力を次(右)の関数の入力として渡すため演算子

summarize は、ある変数の平均値や標準偏差などの記述統計量を計算することができる関数である。例えば、dataというデータセットに含まれる var_name という変数の平均値を計算し、それを M という変数名として定義する場合、以下のコマンドを用いる(以下のコマンドは見本コードである)。

summarize(data, M = mean(var_name))

mutate は、データセットに引数内で指定した定義の変数(列)を追加する関数である。例えば、以下の見本コードにような指示によって、data というデータセットに対し、definition で定義した変数をnew_varとして追加することができる。実際の分析でdefinitionを定義する場合には、様々な関数や論理式を利用する事が多い。例えば、“new_var = var1/100” という定義を用いれば、var1を1/100倍した値をnew_varとして定義することになる。また、“new_var = var1 – mean(var1)”という定義を用いれば、var1の観測値からvar1の平均値を引いた値をnew_varとしている。なお、このような操作化を一般的に「中心化」と呼ぶ。

mutate(data, new_var = definition)

また、mutate関数の利用においては、条件分岐を用いた変数の作成を行うこともある。そのように、研究者がある変数の値に応じて異なる値を変数を作成するときには、mutate内で、ifelse()関数を用いる事が多い。ifelse() 内の第一引数は条件、第二引数は条件が満たされたときの処理、第三引数は条件が満たされないときの処理をそれぞれ表す。なお、特定の条件の指定には “==” (同値), “>=”(以上), “<=”(以下) を使う。具体的には、var1 が2ならば1をとり、それ以外であれば0をとるという条件でnew_varを作成するという指示は、以下のようになる(以下は見本コードである)。

mutate(data, new_var = ifelse(var1 == 2, 1, 0))

filter関数は、データから特定の条件に合致する行だけ取り出す場合に用いる関数である。例えば、男性(gender == “male”)のサンプル情報のみ抽出したい場合には以下のような指示になる。

filter(data, gender == "male")

なお、特定の条件以外のものを指定したいときは、 という論理式 “!=” (not equal) を使う。男性以外の行を選ぶための指示は、以下の通りになる。

filter(data, gender != "male")

select関数は、特定の変数(列)を選んで新たなデータフレームを作成することができる関数である。例えば、dataというデータセットから、var1、var2、var3 という変数(列)を抽出して、data2というdataframeとして定義するには、以下のような指示になる。

data2<- select(data, var1, var2, var3)

反対に、取り除きたい変数を指定するときには、以下のように “-” を使う。

data2<- select(data, -var1)

列の指定方法には、いくつかのやり方が存在する。並んでいる列をまとめて指定するときは:(コロン)を使う。例えば、var1からvar5までの列をまとめて抽出し、それをdata2として定義するのは以下のようにできる。

data2<- select(data, var1:var5)

また、tidyverseのstarts_with()(ends_with())を使うことで、変数名の冒頭(末尾)が特定の文字列から始まる変数を指定するようなことも可能である。例えば、“v” という文字から始まる変数を取り出すための指示は、いかのようになる。

data3<- select(data, starts_with("v"))

arrangeは、データの並べかえを可能にする関数である。例えば、以下ではvar1の値が小さい順(昇順)に並べ替えるような指示を示す。一方で、降順にする場合は、desc(var1)と引数を指定する必要がある2

data2 <- arrange(data, var1) 
data2 <- arrange(data, desc(var1)) 

また、tidyverse環境において、変数名を変更することも、rename() 関数で可能になる。以下の指示によって、var_name という変数を new_name に変更する事ができる。

data3 <- rename(data2, new_name = var_name)

dplyr を活用すると、パイプ演算子(%>%)が使える(ショートカット: command (control) + Shift + m)。パイプ演算子は、左側の処理結果を演算子右側の関数の第一引数として利用するための指示である。たとえば、以下のコマンドではまず \(\small 10-6\) が計算され、その結果である “4” が sqrt() の引数として利用される(sqrt(4) は 2)。

(10-6) %>% sqrt()
## [1] 2

パイプ演算子は、複数のデータ操作処理を連続して行う際に便利である。例えば、顧客の情報を含むデータセット(data)から、男性に該当する情報のみを抽出し、var1(例、購買額)についてのランキングを作成したうえでいくつかの変数を含んだデータセット(new_data)を作成する場合を考える。その際に実行すべき作業とそれらに対応する関数は以下のように示すことができる。

  1. 男性の情報だけ抜き出す(filter)
  2. Var1の値について降順に並べ替える(arrange)
  3. 第一位から最下位までの順位を割り当てた ranking 変数を作る(mutate)
  4. var1 , var2, var3, var4, rankingだけ残し(select) new_dataとして定義する

上記の作業を一気に行うためのコードをパイプ演算子を使わずに書くと以下の様になる(以下は見本コード)。

new_data <- select(
 mutate(
  arrange(
   filter(data, gender == "male"),
   desc(var1)),
   ranking = 1:n()),
  var1, var2, var3, var4, ranking)

パイプ演算子を使わない場合、先に実行する処理が内側に来ており、一見して何を行っているのか理解するのが難しい。一方でパイプ演算子を使い、左側の処理結果を演算子右側の関数の第一引数として利用すると、以下のように書き換えることができる。

new_data <- data %>%
 filter(gender == "male")%>%
 arrange(desc(var1)) %>%
 mutate(ranking = 1:n()) %>% 
 select(var1, var2, var3, var4, ranking)

パイプ演算子の利用により、各関数の処理を一つの行で示せる。また、処理の順番通りに関数を記載することが可能なので、コードの記述容易性と可読性の両方が高まる。また、パイプ演算子による操作は次の関数の第一引数以外に反映されることも可能である。第一引数以外の引数に左側の処理結果を反映させる際には、該当する箇所に “.” (ドット)を使う。たとえば、\(\small 10-2\)の計算結果を用いて2から8までの偶数で構成されるベクトルを返すためのコードは以下のように書くことができる。

(10-2) %>% 
  seq(from = 2, to = ., by = 2)
## [1] 2 4 6 8

データの整形・処理作業が終わったら、そのデータを自身のコンピュータ内のストレージに保存したいと考えるかもしれない。Rでは、外部への書き出しという形でデータを保存することが可能である。例えば、df という名前のデータフレームをnew_dataというファイル名で、dataというディレクトリにcsv形式を用いて保存するためには、以下のようなコードを用いる(以下は見本コード)。また、csv以外にもファイル形式は選択可能であり、例えばRのデータ形式(.Rds)で保存する場合には、“#Rds” 以降のコードを用いる。

readr::write_csv(df, path = "data/new_data.csv")

#Rds
readr::write_rds(df, path = "data/new_data.Rds")

3.3.2 企業データの処理

これまでに学んだデータ処理の手法を実行するために、本節では、 MktRes_firmdata.xlsxデータを用いる。このデータをwebサイトより data ディレクトリにダウンロードし、以下の要領で読み込んでほしい。

firmdata <- readxl::read_xlsx("data/MktRes_firmdata.xlsx")

このデータは、小売・サービス分野の企業約160社(企業数は年によって異なる)に関する2010年から2019年までの財務データである(計1440件)。このデータは、日本生産性本部における顧客満足度調査の対象になっている企業リストを作成し、その企業の中から金融領域の企業や、データを入手できなかった一部の企業を教育的意図から排除したものである。したがって、日本の小売・サービス分野において全国的に知名度のある代表的な企業の財務データ(の一部)だと考えられる。

なお、本データには以下の変数が含まれており、データ内の単位は従業員数(人)を除き百万円である。

  • fyear: 決算年
  • legalname: 企業名
  • ind_en: 日経業種名(英文)
  • parent:親会社名(もしあれば)
  • fiscal_month: 決算月
  • current_liability: 流動負債
  • ltloans: 長期借入金
  • total_liability: 負債合計
  • current_assets: 流動資産
  • ppent: 有形固定資産
  • total_assets: 資産合計
  • net_assets_per_capital: 純資産合計/資本合計
  • sales: 売上高
  • sga: 販売費及び一般管理費
  • operating_profit: 営業利益
  • net_profit: 当期純利益
  • pnet_profit: 親会社株主に帰属する当期純利益(連結)/当期利益(単独)
  • re: 利益剰余金
  • adv: 広告・宣伝費
  • labor_cost: 人件費
  • rd: 研究開発費
  • other_sg: その他販売費及び一般管理費
  • emp: 期末従業員数
  • temp: 平均臨時従業員数
  • tempratio: temp/(emp+temp)
  • indgrowth: 産業成長率
  • adint: 広告集中率(adv/sales)
  • rdint: 研究集中率(rd/sales)
  • mkexp: (sga - rd) / sales
  • op: operating_profit / sales
  • roa: pnet_profit / total_assets

本データセットは、複数年にわたる複数サンプルからのデータであり、一般的にこのような構造のデータをパネルデータという。

ここではこのデータを用いて、以下の作業を行う。

  1. 2018年度のデータのみを抽出する。
  2. 企業名、年、売上高、人件費、期末従業員数、平均臨時従業員数のみの変数を含むデータセットにする。
  3. 労働単価(人件費/(期末従業員数+平均臨時従業員数))変数を作成する。
  4. 労働単価の高い順に並び替えてトップ10企業を出力する。
firm2018_check <- firmdata %>% 
  filter(fyear == 2018) %>% 
  select(legalname, fyear, sales, labor_cost, emp, temp) %>% 
  mutate(wage = labor_cost/(temp+emp), na.rm=TRUE) %>% 
  arrange(desc(wage))

head(firm2018_check, n = 10)
## # A tibble: 10 × 8
##    legalname                    fyear   sales labor_cost   emp  temp  wage na.rm
##    <chr>                        <dbl>   <dbl>      <dbl> <dbl> <dbl> <dbl> <lgl>
##  1 株式会社リクルート            2018 2310756     388583 45856  2449  8.04 TRUE 
##  2 株式会社 大丸松坂屋百貨店     2018  459840      62692  6695  3581  6.10 TRUE 
##  3 株式会社 帝国ホテル           2018   58426      17307  1940   998  5.89 TRUE 
##  4 株式会社 髙島屋               2018  912848      83779  7761  8849  5.04 TRUE 
##  5 株式会社コメリ                2018  346862      43991  4646  4777  4.67 TRUE 
##  6 株式会社オートバックスセブン  2018  213840      22139  4171   747  4.50 TRUE 
##  7 株式会社ロイヤルホテル        2018   40884      13115  2049   894  4.46 TRUE 
##  8 オルビス株式会社              2018  248574      28555  4181  2330  4.39 TRUE 
##  9 株式会社ファンケル            2018  122496      15103  1381  2213  4.20 TRUE 
## 10 近畿日本ツーリスト株式会社    2018  411821      38186  6956  2189  4.18 TRUE

このように、データの中から研究課題と整合的な情報を抽出したり、変数を作成したりすることができる。ただし、研究者にとって都合の良い結果を得るために恣意的に用いるデータを制限、操作することは、研究不正となる。そのため、実際の研究では、どのようなデータ・情報を用いるかについて事前に計画しておく必要がある。


  1. “desc”は、descending orderの略であり、降順を表す。↩︎