ここで学ぶこと

{tidyverse} を使って、取り込んだデータをクリーニングする方法を紹介します

ここで解説する専門用語

欠損値、データクリーニング、データ形式(ワイド、ロング)

  • ここで使う Rパッケージ {tidyverse} をロードする
library(haven)
library(readxl)
library(tidyverse)
── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
✔ ggplot2 3.3.6     ✔ purrr   0.3.4
✔ tibble  3.1.8     ✔ dplyr   1.0.9
✔ tidyr   1.2.0     ✔ stringr 1.4.1
✔ readr   2.1.2     ✔ forcats 0.5.1
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
  • {tidyverse} には8つのパッケージが含まれている
  • データを読み込むために必要なのは readr

1. 各国 GDP データのクリーニング

  • データは RStudio に読み込むだけですぐに分析に使える訳ではない
  • 「データ分析に適したデータ」に「整備」する必要があり = data cleaning
  • 計量分析の核心はデータクリーニングにあり
  • ここでは「様々なファイル形式のデータ読み込み」で紹介した 2 つのデータ (wb_gdp_pc.csvFH_Country.xls) のデータクリーニングについて解説する

1.1 データの読み取りとクリーニング

  • 各国の一人あたりGDPデータ data/wb_gdp_pc.csvをダウンロードして読み込む
  • Rプロジェクトフォルダの中に data というフォルダを作成
  • ダウンロードした wb_gdp_pc.csv ファイルを data の中に入れる
  • .csvファイルの読み取りには {tidyverse} の中に含まれる read_csv()関数を使ってみる
  • (注意:Rの標準関数は read.csv()
wb_gdp <- read_csv("data/wb_gdp_pc.csv")
New names:
• `` -> `...3`
Warning: One or more parsing issues, see `problems()` for details
Rows: 266 Columns: 3
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (3): Data Source, World Development Indicators, ...3

ℹ 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.

Warning: Missing column names filled in : ’X3” [3] に注意

  • Warning・・Error ほど深刻ではないが、何か問題があるという警告

Warning への対処方法

  • データが読み取れているかどうか最初の 10 行を表示させて確かめる
print(wb_gdp) # head(wb_gdp) だと最初の 6 行を表示できる  
# A tibble: 266 × 3
   `Data Source`        `World Development Indicators` ...3                     
   <chr>                <chr>                          <chr>                    
 1 Last Updated Date    2019-03-21                      <NA>                    
 2 Country Name         Country Code                   "Indicator Name,Indicato…
 3 Aruba                ABW                            "GDP per capita (current…
 4 Afghanistan          AFG                            "GDP per capita (current…
 5 Angola               AGO                            "GDP per capita (current…
 6 Albania              ALB                            "GDP per capita (current…
 7 Andorra              AND                            "GDP per capita (current…
 8 Arab World           ARB                            "GDP per capita (current…
 9 United Arab Emirates ARE                            "GDP per capita (current…
10 Argentina            ARG                            "GDP per capita (current…
# … with 256 more rows

表示したい行の指定

print(wb_gdp, n = Inf)・・・全ての行を表示させたい場合
print(wb_gdp, n = 20)・・・最初の 20 行を表示させたい場合
  • 1 行目 (Last Updated Date 2019-03-21…) は不要
  • LibreOffice(もしくは Excel)を使って data にある wb_gdp_pc.csv を確かめる

注意:黄色のハイライトは著者がわかりやすくするために付けました

  • read_csv()関数を使うと、オリジナルデータの 1 行目を「変数名」として読み取る
  • 5 行目を「変数名」として RStudio に読み取らせたい
    → 1行目から4行目(黄色い部分)をスキップ skip して読み込む
wb_gdp <- read_csv("data/wb_gdp_pc.csv", skip = 4)
New names:
Rows: 264 Columns: 64
── Column specification
──────────────────────────────────────────────────────── Delimiter: "," chr
(4): Country Name, Country Code, Indicator Name, Indicator Code dbl (58): 1960,
1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, ... lgl (2): 2018,
...64
ℹ 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.
• `` -> `...64`
  • str()関数を使ってデータが読み取れたかどうか確かめる
str(wb_gdp)
spec_tbl_df [264 × 64] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ Country Name  : chr [1:264] "Aruba" "Afghanistan" "Angola" "Albania" ...
 $ Country Code  : chr [1:264] "ABW" "AFG" "AGO" "ALB" ...
 $ Indicator Name: chr [1:264] "GDP per capita (current US$)" "GDP per capita (current US$)" "GDP per capita (current US$)" "GDP per capita (current US$)" ...
 $ Indicator Code: chr [1:264] "NY.GDP.PCAP.CD" "NY.GDP.PCAP.CD" "NY.GDP.PCAP.CD" "NY.GDP.PCAP.CD" ...
 $ 1960          : num [1:264] NA 59.8 NA NA NA ...
 $ 1961          : num [1:264] NA 59.9 NA NA NA ...
 $ 1962          : num [1:264] NA 58.5 NA NA NA ...
 $ 1963          : num [1:264] NA 78.8 NA NA NA ...
 $ 1964          : num [1:264] NA 82.2 NA NA NA ...
 $ 1965          : num [1:264] NA 101 NA NA NA ...
 $ 1966          : num [1:264] NA 138 NA NA NA ...
 $ 1967          : num [1:264] NA 161 NA NA NA ...
 $ 1968          : num [1:264] NA 130 NA NA NA ...
 $ 1969          : num [1:264] NA 130 NA NA NA ...
 $ 1970          : num [1:264] NA 157 NA NA 3239 ...
 $ 1971          : num [1:264] NA 160 NA NA 3498 ...
 $ 1972          : num [1:264] NA 136 NA NA 4217 ...
 $ 1973          : num [1:264] NA 144 NA NA 5342 ...
 $ 1974          : num [1:264] NA 175 NA NA 6320 ...
 $ 1975          : num [1:264] NA 188 NA NA 7169 ...
 $ 1976          : num [1:264] NA 199 NA NA 7152 ...
 $ 1977          : num [1:264] NA 226 NA NA 7751 ...
 $ 1978          : num [1:264] NA 249 NA NA 9130 ...
 $ 1979          : num [1:264] NA 278 NA NA 11821 ...
 $ 1980          : num [1:264] NA 275 664 NA 12377 ...
 $ 1981          : num [1:264] NA 266 600 NA 10372 ...
 $ 1982          : num [1:264] NA NA 579 NA 9610 ...
 $ 1983          : num [1:264] NA NA 582 NA 8023 ...
 $ 1984          : num [1:264] NA NA 597 639 7729 ...
 $ 1985          : num [1:264] NA NA 712 640 7774 ...
 $ 1986          : num [1:264] 6473 NA 648 694 10362 ...
 $ 1987          : num [1:264] 7886 NA 721 675 12616 ...
 $ 1988          : num [1:264] 9765 NA 762 653 14304 ...
 $ 1989          : num [1:264] 11392 NA 863 698 15166 ...
 $ 1990          : num [1:264] 12307 NA 923 617 18879 ...
 $ 1991          : num [1:264] 13496 NA 845 337 19533 ...
 $ 1992          : num [1:264] 14047 NA 641 201 20548 ...
 $ 1993          : num [1:264] 14937 NA 430 367 16516 ...
 $ 1994          : num [1:264] 16241 NA 321 586 16235 ...
 $ 1995          : num [1:264] 16439 NA 388 751 18461 ...
 $ 1996          : num [1:264] 16586 NA 513 1010 19017 ...
 $ 1997          : num [1:264] 17928 NA 507 717 18353 ...
 $ 1998          : num [1:264] 19078 NA 420 814 18895 ...
 $ 1999          : num [1:264] 19356 NA 386 1033 19262 ...
 $ 2000          : num [1:264] 20621 NA 555 1127 21937 ...
 $ 2001          : num [1:264] 20669 NA 526 1282 22229 ...
 $ 2002          : num [1:264] 20437 184 870 1425 24741 ...
 $ 2003          : num [1:264] 20834 196 979 1846 32776 ...
 $ 2004          : num [1:264] 22570 217 1248 2374 38503 ...
 $ 2005          : num [1:264] 23300 248 1891 2674 41282 ...
 $ 2006          : num [1:264] 24046 269 2585 2973 43749 ...
 $ 2007          : num [1:264] 25836 366 3108 3595 48583 ...
 $ 2008          : num [1:264] 27086 370 4069 4371 47786 ...
 $ 2009          : num [1:264] 24631 444 3118 4114 43339 ...
 $ 2010          : num [1:264] 23513 551 3586 4094 39736 ...
 $ 2011          : num [1:264] 24984 599 4616 4437 41099 ...
 $ 2012          : num [1:264] 24710 649 5102 4248 38391 ...
 $ 2013          : num [1:264] 25018 648 5258 4413 40620 ...
 $ 2014          : num [1:264] 25528 625 5413 4579 42295 ...
 $ 2015          : num [1:264] 25796 590 4171 3953 36038 ...
 $ 2016          : num [1:264] 25252 550 3510 4132 37232 ...
 $ 2017          : num [1:264] 25655 550 4100 4538 39147 ...
 $ 2018          : logi [1:264] NA NA NA NA NA NA ...
 $ ...64         : logi [1:264] NA NA NA NA NA NA ...
 - attr(*, "spec")=
  .. cols(
  ..   `Country Name` = col_character(),
  ..   `Country Code` = col_character(),
  ..   `Indicator Name` = col_character(),
  ..   `Indicator Code` = col_character(),
  ..   `1960` = col_double(),
  ..   `1961` = col_double(),
  ..   `1962` = col_double(),
  ..   `1963` = col_double(),
  ..   `1964` = col_double(),
  ..   `1965` = col_double(),
  ..   `1966` = col_double(),
  ..   `1967` = col_double(),
  ..   `1968` = col_double(),
  ..   `1969` = col_double(),
  ..   `1970` = col_double(),
  ..   `1971` = col_double(),
  ..   `1972` = col_double(),
  ..   `1973` = col_double(),
  ..   `1974` = col_double(),
  ..   `1975` = col_double(),
  ..   `1976` = col_double(),
  ..   `1977` = col_double(),
  ..   `1978` = col_double(),
  ..   `1979` = col_double(),
  ..   `1980` = col_double(),
  ..   `1981` = col_double(),
  ..   `1982` = col_double(),
  ..   `1983` = col_double(),
  ..   `1984` = col_double(),
  ..   `1985` = col_double(),
  ..   `1986` = col_double(),
  ..   `1987` = col_double(),
  ..   `1988` = col_double(),
  ..   `1989` = col_double(),
  ..   `1990` = col_double(),
  ..   `1991` = col_double(),
  ..   `1992` = col_double(),
  ..   `1993` = col_double(),
  ..   `1994` = col_double(),
  ..   `1995` = col_double(),
  ..   `1996` = col_double(),
  ..   `1997` = col_double(),
  ..   `1998` = col_double(),
  ..   `1999` = col_double(),
  ..   `2000` = col_double(),
  ..   `2001` = col_double(),
  ..   `2002` = col_double(),
  ..   `2003` = col_double(),
  ..   `2004` = col_double(),
  ..   `2005` = col_double(),
  ..   `2006` = col_double(),
  ..   `2007` = col_double(),
  ..   `2008` = col_double(),
  ..   `2009` = col_double(),
  ..   `2010` = col_double(),
  ..   `2011` = col_double(),
  ..   `2012` = col_double(),
  ..   `2013` = col_double(),
  ..   `2014` = col_double(),
  ..   `2015` = col_double(),
  ..   `2016` = col_double(),
  ..   `2017` = col_double(),
  ..   `2018` = col_logical(),
  ..   ...64 = col_logical()
  .. )
 - attr(*, "problems")=<externalptr> 
  • RStudio はオリジナルデータの 5 行目 (Country Name, Country Code など)を「変数名」として読み取っている
  • Country NameCountry Codeは文字列データ <chr>1960などは数値データ <dbl> であることを確認
  • NA とは R における欠損値 (missing value)のこと
  • ちゃんと読み取れていることがわかる
  • 変数名をチェック
names(wb_gdp)
 [1] "Country Name"   "Country Code"   "Indicator Name" "Indicator Code"
 [5] "1960"           "1961"           "1962"           "1963"          
 [9] "1964"           "1965"           "1966"           "1967"          
[13] "1968"           "1969"           "1970"           "1971"          
[17] "1972"           "1973"           "1974"           "1975"          
[21] "1976"           "1977"           "1978"           "1979"          
[25] "1980"           "1981"           "1982"           "1983"          
[29] "1984"           "1985"           "1986"           "1987"          
[33] "1988"           "1989"           "1990"           "1991"          
[37] "1992"           "1993"           "1994"           "1995"          
[41] "1996"           "1997"           "1998"           "1999"          
[45] "2000"           "2001"           "2002"           "2003"          
[49] "2004"           "2005"           "2006"           "2007"          
[53] "2008"           "2009"           "2010"           "2011"          
[57] "2012"           "2013"           "2014"           "2015"          
[61] "2016"           "2017"           "2018"           "...64"         

*必要な変数だけを選ぶ**
- ここからは、このデータを使って分析する上で障害となる問題を解決する必要がある
- 内容が不明な変数(X64)の内容を確認する

wb_gdp$X64
NULL
  • 中身は全て NA なのでX64は分析には不要と判断

→ 必要な変数は Country Name, 1960から2018まで

gdp <- wb_gdp  %>%
  select("Country Name", 
         "1960":"2018")  
names(gdp)
 [1] "Country Name" "1960"         "1961"         "1962"         "1963"        
 [6] "1964"         "1965"         "1966"         "1967"         "1968"        
[11] "1969"         "1970"         "1971"         "1972"         "1973"        
[16] "1974"         "1975"         "1976"         "1977"         "1978"        
[21] "1979"         "1980"         "1981"         "1982"         "1983"        
[26] "1984"         "1985"         "1986"         "1987"         "1988"        
[31] "1989"         "1990"         "1991"         "1992"         "1993"        
[36] "1994"         "1995"         "1996"         "1997"         "1998"        
[41] "1999"         "2000"         "2001"         "2002"         "2003"        
[46] "2004"         "2005"         "2006"         "2007"         "2008"        
[51] "2009"         "2010"         "2011"         "2012"         "2013"        
[56] "2014"         "2015"         "2016"         "2017"         "2018"        

変数名の修正

  • Country Namecountry と簡略化する
  • 変数名にスペースが入っている場合、スペースを取り去った変数名に変更する
  • 変数名にスペースが入っていると、RStudio が認識しないため
gdp <- gdp %>% 
  rename(country = "Country Name")
  • 確認する
names(gdp)
 [1] "country" "1960"    "1961"    "1962"    "1963"    "1964"    "1965"   
 [8] "1966"    "1967"    "1968"    "1969"    "1970"    "1971"    "1972"   
[15] "1973"    "1974"    "1975"    "1976"    "1977"    "1978"    "1979"   
[22] "1980"    "1981"    "1982"    "1983"    "1984"    "1985"    "1986"   
[29] "1987"    "1988"    "1989"    "1990"    "1991"    "1992"    "1993"   
[36] "1994"    "1995"    "1996"    "1997"    "1998"    "1999"    "2000"   
[43] "2001"    "2002"    "2003"    "2004"    "2005"    "2006"    "2007"   
[50] "2008"    "2009"    "2010"    "2011"    "2012"    "2013"    "2014"   
[57] "2015"    "2016"    "2017"    "2018"   
  • gdp が含むデータ数 (N) と変数の数を確認
dim(gdp)
[1] 264  60
  • データフレーム gdp の観測数(N) は264、変数の数は 60 だとわかる  

  • paged_table() 関数を使って、読み込んで修正を加えたデータの様子を表示させる

rmarkdown::paged_table(gdp)

1.2 データ形式を変更(ワイド→ロング)

  • このデータはワイド形式なので、実際に分析する際には ロング形式に変換する必要がある

データ形式変更のイメージ図

  • tidyr::pivot_longer() 関数を使ってデータ形式を変換する
  • 変換したデータフレームに gdp_long と名前をつける
gdp_long <- gdp %>% 
  tidyr::pivot_longer("1960":"2018",         # 変換したい変数の範囲を指定  
                      names_to = "year",     #ワイドの「変数名」を year の中に入れる
                      values_to = "GDP") %>% #ワイドの「変数の値」を GDP の中に入れる
  drop_na()                                  # 欠損値 (na) を表示しない  
  • DT::datatable() 関数を使って gdp_long の中身を確認する
DT::datatable(gdp_long)
  • gdp_long が含む変数の class を確認する
str(gdp_long)
tibble [11,824 × 3] (S3: tbl_df/tbl/data.frame)
 $ country: chr [1:11824] "Aruba" "Aruba" "Aruba" "Aruba" ...
 $ year   : chr [1:11824] "1986" "1987" "1988" "1989" ...
 $ GDP    : num [1:11824] 6473 7886 9765 11392 12307 ...
  • yearclass を文字列データ (chracter) から数値データ (numeric) に変換する
gdp_long$year <- as.numeric(gdp_long$year)
  • 確認する
str(gdp_long)
tibble [11,824 × 3] (S3: tbl_df/tbl/data.frame)
 $ country: chr [1:11824] "Aruba" "Aruba" "Aruba" "Aruba" ...
 $ year   : num [1:11824] 1986 1987 1988 1989 1990 ...
 $ GDP    : num [1:11824] 6473 7886 9765 11392 12307 ...

1.2 データの可視化

  • ロング形式に変換されたデータを使うと様々な分析が可能になる
  • 例えば、日本と中国の一人あたり GDP の推移 (1980-2017) を可視化してみる
  • 日本と中国のデータだけを抜き出し jpn.chi とデータフレーム名をつける
jpn.chi <- gdp_long %>% 
  filter(country == "Japan" | country == "China")

ggplot で文字バケしない設定

theme_set(theme_classic(base_size = 10,
                        base_family = "HiraginoSans-W3"))
jpn.chi %>% 
  ggplot(aes(x = year, y = GDP,
             color = country, 
             linetype = country, 
             shape = country)) +
  geom_point() +
  geom_line() +
  ggtitle("日本と中国1人あたりGDPの推移: 1980-2017") +
  labs(x = "Year", y = "1人あたりGDP (US$)") +
  theme(legend.position = c(0.1, 0.8)) +
  xlim(1980, 2017) # 2018年データは欠損のため省く

2. 民主主義度データのクリーニング

2.1 データの読み取りとクリーニング

  • Freedom House が公開している 1972年から2016年までの各国別政治的権利 (PR: political rights)、市民の自由度 (CL: civil liberties)、自由の度合い (Status) に関するデータ  
変数名 データの種類 詳細
PR 数値データ 各国の政治的権利: (最高)1-7(最低)
CL 数値データ 各国の市民の自由度: (最高)1-7(最低)
status カテゴリカル変数 各国の自由度を分類(F: free, PF: partly free, NF: not free)
year カテゴリカル変数 調査した年: 1972-2016
  • PR and CL are measured on a one-to-seven scale, with one representing the highest degree of Freedom and seven the lowest.

  • エクセルファイルのようなバイナリデータを読み込むために必要なパッケージをロードする

  • 詳細は浅野・矢内『Rによる計量政治学』pp.67-68 を参照

library(readxl)
  • ここでは Freedom House のデータセットをダウンロードして読み込む

  • データを読み取る前に、オリジナルデータ FH_Country.xls を開いてみる(LibreOffice もしくは Excel で開く)

  • RStudio の画面左下に3 つのタブが表示されている
  • ここで読み取りたいデータは左下「2番目のタブ」 のデータ (Country Ratings, Statuses)
    → データを読み取る際、sheet = 2と指定

シートの選択と読み取る行の指定

  • 2 枚目のシートを確認してみる

注意:黄色のハイライトは著者がわかりやすくするために付けました

  • 1行目と2行目は不要(黄色い部分) → skip = 2 と指定して3行目から読み取るよう指定
fh <- read_excel("data/FH_Country.xls", 
                 sheet = 2,
                 skip = 2)

変数の class の確認

  • str() 関数を使って変数の class をチェック
str(fh)
tibble [205 × 133] (S3: tbl_df/tbl/data.frame)
 $ ...1        : chr [1:205] "Afghanistan" "Albania" "Algeria" "Andorra" ...
 $ PR...2      : chr [1:205] "4" "7" "6" "4" ...
 $ CL...3      : chr [1:205] "5" "7" "6" "3" ...
 $ Status...4  : chr [1:205] "PF" "NF" "NF" "PF" ...
 $ PR...5      : chr [1:205] "7" "7" "6" "4" ...
 $ CL...6      : chr [1:205] "6" "7" "6" "4" ...
 $ Status...7  : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...8      : chr [1:205] "7" "7" "6" "4" ...
 $ CL...9      : chr [1:205] "6" "7" "6" "4" ...
 $ Status...10 : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...11     : chr [1:205] "7" "7" "7" "4" ...
 $ CL...12     : chr [1:205] "6" "7" "6" "4" ...
 $ Status...13 : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...14     : chr [1:205] "7" "7" "6" "4" ...
 $ CL...15     : chr [1:205] "6" "7" "6" "4" ...
 $ Status...16 : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...17     : chr [1:205] "6" "7" "6" "-" ...
 $ CL...18     : chr [1:205] "6" "7" "6" "-" ...
 $ Status...19 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...20     : chr [1:205] "7" "7" "6" "-" ...
 $ CL...21     : chr [1:205] "7" "7" "6" "-" ...
 $ Status...22 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...23     : chr [1:205] "7" "7" "6" "-" ...
 $ CL...24     : chr [1:205] "7" "7" "6" "-" ...
 $ Status...25 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...26     : chr [1:205] "7" "7" "6" "-" ...
 $ CL...27     : chr [1:205] "7" "7" "6" "-" ...
 $ Status...28 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...29     : chr [1:205] "7" "7" "6" "-" ...
 $ CL...30     : chr [1:205] "7" "7" "6" "-" ...
 $ Status...31 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...32     : chr [1:205] "7" "7" "6" "-" ...
 $ CL...33     : chr [1:205] "7" "7" "6" "-" ...
 $ Status...34 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...35     : chr [1:205] "7" "7" "6" "-" ...
 $ CL...36     : chr [1:205] "7" "7" "6" "-" ...
 $ Status...37 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...38     : chr [1:205] "7" "7" "6" "-" ...
 $ CL...39     : chr [1:205] "7" "7" "6" "-" ...
 $ Status...40 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...41     : chr [1:205] "7" "7" "6" "-" ...
 $ CL...42     : chr [1:205] "7" "7" "6" "-" ...
 $ Status...43 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...44     : chr [1:205] "7" "7" "6" "-" ...
 $ CL...45     : chr [1:205] "7" "7" "6" "-" ...
 $ Status...46 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...47     : chr [1:205] "6" "7" "5" "-" ...
 $ CL...48     : chr [1:205] "6" "7" "6" "-" ...
 $ Status...49 : chr [1:205] "NF" "NF" "NF" "-" ...
 $ PR...50     : chr [1:205] "7" "7" "6" "-" ...
 $ CL...51     : chr [1:205] "7" "7" "4" "-" ...
 $ Status...52 : chr [1:205] "NF" "NF" "PF" "-" ...
 $ PR...53     : chr [1:205] "7" "7" "4" "-" ...
 $ CL...54     : chr [1:205] "7" "6" "4" "-" ...
 $ Status...55 : chr [1:205] "NF" "NF" "PF" "-" ...
 $ PR...56     : chr [1:205] "7" "4" "4" "-" ...
 $ CL...57     : chr [1:205] "7" "4" "4" "-" ...
 $ Status...58 : chr [1:205] "NF" "PF" "PF" "-" ...
 $ PR...59     : chr [1:205] "6" "4" "7" "-" ...
 $ CL...60     : chr [1:205] "6" "3" "6" "-" ...
 $ Status...61 : chr [1:205] "NF" "PF" "NF" "-" ...
 $ PR...62     : chr [1:205] "7" "2" "7" "2" ...
 $ CL...63     : chr [1:205] "7" "4" "6" "1" ...
 $ Status...64 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...65     : chr [1:205] "7" "3" "7" "1" ...
 $ CL...66     : chr [1:205] "7" "4" "7" "1" ...
 $ Status...67 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...68     : chr [1:205] "7" "3" "6" "1" ...
 $ CL...69     : chr [1:205] "7" "4" "6" "1" ...
 $ Status...70 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...71     : chr [1:205] "7" "4" "6" "1" ...
 $ CL...72     : chr [1:205] "7" "4" "6" "1" ...
 $ Status...73 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...74     : chr [1:205] "7" "4" "6" "1" ...
 $ CL...75     : chr [1:205] "7" "4" "6" "1" ...
 $ Status...76 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...77     : chr [1:205] "7" "4" "6" "1" ...
 $ CL...78     : chr [1:205] "7" "5" "5" "1" ...
 $ Status...79 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...80     : chr [1:205] "7" "4" "6" "1" ...
 $ CL...81     : chr [1:205] "7" "5" "5" "1" ...
 $ Status...82 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...83     : chr [1:205] "7" "4" "6" "1" ...
 $ CL...84     : chr [1:205] "7" "5" "5" "1" ...
 $ Status...85 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...86     : chr [1:205] "7" "3" "6" "1" ...
 $ CL...87     : chr [1:205] "7" "4" "5" "1" ...
 $ Status...88 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...89     : chr [1:205] "6" "3" "6" "1" ...
 $ CL...90     : chr [1:205] "6" "3" "5" "1" ...
 $ Status...91 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...92     : chr [1:205] "6" "3" "6" "1" ...
 $ CL...93     : chr [1:205] "6" "3" "5" "1" ...
 $ Status...94 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...95     : chr [1:205] "5" "3" "6" "1" ...
 $ CL...96     : chr [1:205] "6" "3" "5" "1" ...
 $ Status...97 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...98     : chr [1:205] "5" "3" "6" "1" ...
 $ CL...99     : chr [1:205] "5" "3" "5" "1" ...
  [list output truncated]
  • 全ての変数の class が chr(= character: 文字列データ)
  • 国名やステータスが文字列データなのは当然
  • しかし PR (political rights)CL (civil liberty) は数値データのはず → これは問題

解決策:

  • データを見てみると、ところどころ - という記号が含まれている
  • これは Freedom House のデータセットにおける欠損値を示している
  • Rではデフォルトで「空欄」を欠損値として認識し - で表す
    "-"欠損値だと R に認識させる必要あり
    na = "-" と設定 
fh <- read_excel("data/FH_Country.xls", 
                 sheet = 2, 
                 skip = 2,
                 na = "-") # NA = "-" でも可
  • str() 関数を使って変数の class をチェック
str(fh)
tibble [205 × 133] (S3: tbl_df/tbl/data.frame)
 $ ...1        : chr [1:205] "Afghanistan" "Albania" "Algeria" "Andorra" ...
 $ PR...2      : chr [1:205] "4" "7" "6" "4" ...
 $ CL...3      : chr [1:205] "5" "7" "6" "3" ...
 $ Status...4  : chr [1:205] "PF" "NF" "NF" "PF" ...
 $ PR...5      : num [1:205] 7 7 6 4 NA NA 2 NA 1 1 ...
 $ CL...6      : num [1:205] 6 7 6 4 NA NA 2 NA 1 1 ...
 $ Status...7  : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...8      : num [1:205] 7 7 6 4 NA NA 2 NA 1 1 ...
 $ CL...9      : num [1:205] 6 7 6 4 NA NA 4 NA 1 1 ...
 $ Status...10 : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...11     : num [1:205] 7 7 7 4 6 NA 2 NA 1 1 ...
 $ CL...12     : num [1:205] 6 7 6 4 6 NA 4 NA 1 1 ...
 $ Status...13 : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...14     : num [1:205] 7 7 6 4 6 NA 6 NA 1 1 ...
 $ CL...15     : num [1:205] 6 7 6 4 6 NA 5 NA 1 1 ...
 $ Status...16 : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...17     : num [1:205] 6 7 6 NA 7 NA 6 NA 1 1 ...
 $ CL...18     : num [1:205] 6 7 6 NA 7 NA 6 NA 1 1 ...
 $ Status...19 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...20     : num [1:205] 7 7 6 NA 7 NA 6 NA 1 1 ...
 $ CL...21     : num [1:205] 7 7 6 NA 7 NA 5 NA 1 1 ...
 $ Status...22 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...23     : num [1:205] 7 7 6 NA 7 NA 6 NA 1 1 ...
 $ CL...24     : num [1:205] 7 7 6 NA 7 NA 5 NA 1 1 ...
 $ Status...25 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...26     : num [1:205] 7 7 6 NA 7 NA 6 NA 1 1 ...
 $ CL...27     : num [1:205] 7 7 6 NA 7 NA 5 NA 1 1 ...
 $ Status...28 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...29     : num [1:205] 7 7 6 NA 7 2 6 NA 1 1 ...
 $ CL...30     : num [1:205] 7 7 6 NA 7 2 5 NA 1 1 ...
 $ Status...31 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...32     : num [1:205] 7 7 6 NA 7 2 3 NA 1 1 ...
 $ CL...33     : num [1:205] 7 7 6 NA 7 3 3 NA 1 1 ...
 $ Status...34 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...35     : num [1:205] 7 7 6 NA 7 2 2 NA 1 1 ...
 $ CL...36     : num [1:205] 7 7 6 NA 7 3 2 NA 1 1 ...
 $ Status...37 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...38     : num [1:205] 7 7 6 NA 7 2 2 NA 1 1 ...
 $ CL...39     : num [1:205] 7 7 6 NA 7 3 2 NA 1 1 ...
 $ Status...40 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...41     : num [1:205] 7 7 6 NA 7 2 2 NA 1 1 ...
 $ CL...42     : num [1:205] 7 7 6 NA 7 3 1 NA 1 1 ...
 $ Status...43 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...44     : num [1:205] 7 7 6 NA 7 2 2 NA 1 1 ...
 $ CL...45     : num [1:205] 7 7 6 NA 7 3 1 NA 1 1 ...
 $ Status...46 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...47     : num [1:205] 6 7 5 NA 7 2 2 NA 1 1 ...
 $ CL...48     : num [1:205] 6 7 6 NA 7 3 1 NA 1 1 ...
 $ Status...49 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...50     : num [1:205] 7 7 6 NA 7 2 1 NA 1 1 ...
 $ CL...51     : num [1:205] 7 7 4 NA 7 3 2 NA 1 1 ...
 $ Status...52 : chr [1:205] "NF" "NF" "PF" NA ...
 $ PR...53     : num [1:205] 7 7 4 NA 7 3 1 NA 1 1 ...
 $ CL...54     : num [1:205] 7 6 4 NA 7 2 3 NA 1 1 ...
 $ Status...55 : chr [1:205] "NF" "NF" "PF" NA ...
 $ PR...56     : num [1:205] 7 4 4 NA 6 3 1 5 1 1 ...
 $ CL...57     : num [1:205] 7 4 4 NA 4 3 3 5 1 1 ...
 $ Status...58 : chr [1:205] "NF" "PF" "PF" NA ...
 $ PR...59     : num [1:205] 6 4 7 NA 6 3 2 4 1 1 ...
 $ CL...60     : num [1:205] 6 3 6 NA 6 3 3 3 1 1 ...
 $ Status...61 : chr [1:205] "NF" "PF" "NF" NA ...
 $ PR...62     : num [1:205] 7 2 7 2 7 4 2 3 1 1 ...
 $ CL...63     : num [1:205] 7 4 6 1 7 3 3 4 1 1 ...
 $ Status...64 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...65     : num [1:205] 7 3 7 1 7 4 2 3 1 1 ...
 $ CL...66     : num [1:205] 7 4 7 1 7 3 3 4 1 1 ...
 $ Status...67 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...68     : num [1:205] 7 3 6 1 6 4 2 4 1 1 ...
 $ CL...69     : num [1:205] 7 4 6 1 6 3 3 4 1 1 ...
 $ Status...70 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...71     : num [1:205] 7 4 6 1 6 4 2 5 1 1 ...
 $ CL...72     : num [1:205] 7 4 6 1 6 3 3 4 1 1 ...
 $ Status...73 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...74     : num [1:205] 7 4 6 1 6 4 2 5 1 1 ...
 $ CL...75     : num [1:205] 7 4 6 1 6 3 3 4 1 1 ...
 $ Status...76 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...77     : num [1:205] 7 4 6 1 6 4 3 4 1 1 ...
 $ CL...78     : num [1:205] 7 5 5 1 6 3 3 4 1 1 ...
 $ Status...79 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...80     : num [1:205] 7 4 6 1 6 4 2 4 1 1 ...
 $ CL...81     : num [1:205] 7 5 5 1 6 3 3 4 1 1 ...
 $ Status...82 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...83     : num [1:205] 7 4 6 1 6 4 1 4 1 1 ...
 $ CL...84     : num [1:205] 7 5 5 1 6 2 2 4 1 1 ...
 $ Status...85 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...86     : num [1:205] 7 3 6 1 6 4 3 4 1 1 ...
 $ CL...87     : num [1:205] 7 4 5 1 6 2 3 4 1 1 ...
 $ Status...88 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...89     : num [1:205] 6 3 6 1 6 4 3 4 1 1 ...
 $ CL...90     : num [1:205] 6 3 5 1 5 2 3 4 1 1 ...
 $ Status...91 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...92     : num [1:205] 6 3 6 1 6 4 2 4 1 1 ...
 $ CL...93     : num [1:205] 6 3 5 1 5 2 2 4 1 1 ...
 $ Status...94 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...95     : num [1:205] 5 3 6 1 6 2 2 5 1 1 ...
 $ CL...96     : num [1:205] 6 3 5 1 5 2 2 4 1 1 ...
 $ Status...97 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...98     : num [1:205] 5 3 6 1 6 2 2 5 1 1 ...
 $ CL...99     : num [1:205] 5 3 5 1 5 2 2 4 1 1 ...
  [list output truncated]
  • ほとんど全ての PR...CL... 変数は数値データ(num) に変更されている  
  • PR...2CL...3 だけが文字列データ (chr) のまま
    → これは問題
    PR...2CL...3 だけが文字列データ (chr) のままである原因を探り、この2 つの変数を数値データ(num) に変更する必要あり

unique()関数を使って、PR...2に含まれる値を確認

unique(fh$PR...2)
[1] "4"    "7"    "6"    NA     "1"    "2"    "5"    "3"    "2(5)"
  • 2(5) という文字列が含まれている!
  • 2(5) 数値ではない → 文字列と認識されている
  • 値が "" で囲まれているのは文字列だから
  • もし値が数値なら "" で囲まれない
  • NA"" で囲まれてない → NA は「特例」で文字列だと見なされていないから
  • 2(5) があるせいでPR...2全体が文字列データと判断されている→ これが原因!

unique()関数を使って、CL...3に含まれる値を確認

unique(fh$CL...3)
[1] "5"    "7"    "6"    "3"    NA     "1"    "4"    "2"    "3(6)"
  • 3(6) という文字列が含まれている!
  • 3(6) 数値ではない → 文字列と認識されている
  • 値が "" で囲まれているのは文字列だから
  • もし値が数値なら "" で囲まれない
  • NA"" で囲まれてない → NA は「特例」で文字列だと見なされていないから
  • 3(6) があるせいでCL...3全体が文字列データと判断されている→ これが原因!

解決策:

if_else()関数を使って異常値を NA と置き換える
PR...2に含まれる異常値2(5)NA に置き換える
CL...3に含まれる異常値3(6)NA に置き換える
- 異常値を NA に置き換えた新たなデータフレームに fh_na と名前を付ける

fh_na <- fh %>% 
  dplyr::mutate(
    PR...2 = if_else(PR...2 == "2(5)", "NA", PR...2),
    CL...3 = if_else(CL...3 == "3(6)", "NA", CL...3)) %>% 
  mutate(across(c(PR...2, CL...3), as.numeric)) # 2つの列に同時に as.numeric を施す
  • unique()関数を使って、PR...2に含まれる値を確認
unique(fh_na$PR...2)
[1]  4  7  6 NA  1  2  5  3
  • 値が "" で囲まれていない → 数値データと認識されている

unique()関数を使って、CL...3に含まれる値を確認

unique(fh_na$CL...3)
[1]  5  7  6  3 NA  1  4  2
  • 値が "" で囲まれていない → 数値データと認識されている

  • str() 関数を使って変数の class をチェック

str(fh_na$PR...2)
 num [1:205] 4 7 6 4 NA NA 6 NA 1 1 ...
str(fh_na$CL...3)
 num [1:205] 5 7 6 3 NA NA 3 NA 1 1 ...
  • PR...2CL...3 が 数値 データ (num) に変換されている

2.2 データ形式を変更: fh_na(ワイド→ロング)

  • 現時点までに修正してきたデータ fh_na の姿を確認
str(fh_na)
tibble [205 × 133] (S3: tbl_df/tbl/data.frame)
 $ ...1        : chr [1:205] "Afghanistan" "Albania" "Algeria" "Andorra" ...
 $ PR...2      : num [1:205] 4 7 6 4 NA NA 6 NA 1 1 ...
 $ CL...3      : num [1:205] 5 7 6 3 NA NA 3 NA 1 1 ...
 $ Status...4  : chr [1:205] "PF" "NF" "NF" "PF" ...
 $ PR...5      : num [1:205] 7 7 6 4 NA NA 2 NA 1 1 ...
 $ CL...6      : num [1:205] 6 7 6 4 NA NA 2 NA 1 1 ...
 $ Status...7  : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...8      : num [1:205] 7 7 6 4 NA NA 2 NA 1 1 ...
 $ CL...9      : num [1:205] 6 7 6 4 NA NA 4 NA 1 1 ...
 $ Status...10 : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...11     : num [1:205] 7 7 7 4 6 NA 2 NA 1 1 ...
 $ CL...12     : num [1:205] 6 7 6 4 6 NA 4 NA 1 1 ...
 $ Status...13 : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...14     : num [1:205] 7 7 6 4 6 NA 6 NA 1 1 ...
 $ CL...15     : num [1:205] 6 7 6 4 6 NA 5 NA 1 1 ...
 $ Status...16 : chr [1:205] "NF" "NF" "NF" "PF" ...
 $ PR...17     : num [1:205] 6 7 6 NA 7 NA 6 NA 1 1 ...
 $ CL...18     : num [1:205] 6 7 6 NA 7 NA 6 NA 1 1 ...
 $ Status...19 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...20     : num [1:205] 7 7 6 NA 7 NA 6 NA 1 1 ...
 $ CL...21     : num [1:205] 7 7 6 NA 7 NA 5 NA 1 1 ...
 $ Status...22 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...23     : num [1:205] 7 7 6 NA 7 NA 6 NA 1 1 ...
 $ CL...24     : num [1:205] 7 7 6 NA 7 NA 5 NA 1 1 ...
 $ Status...25 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...26     : num [1:205] 7 7 6 NA 7 NA 6 NA 1 1 ...
 $ CL...27     : num [1:205] 7 7 6 NA 7 NA 5 NA 1 1 ...
 $ Status...28 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...29     : num [1:205] 7 7 6 NA 7 2 6 NA 1 1 ...
 $ CL...30     : num [1:205] 7 7 6 NA 7 2 5 NA 1 1 ...
 $ Status...31 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...32     : num [1:205] 7 7 6 NA 7 2 3 NA 1 1 ...
 $ CL...33     : num [1:205] 7 7 6 NA 7 3 3 NA 1 1 ...
 $ Status...34 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...35     : num [1:205] 7 7 6 NA 7 2 2 NA 1 1 ...
 $ CL...36     : num [1:205] 7 7 6 NA 7 3 2 NA 1 1 ...
 $ Status...37 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...38     : num [1:205] 7 7 6 NA 7 2 2 NA 1 1 ...
 $ CL...39     : num [1:205] 7 7 6 NA 7 3 2 NA 1 1 ...
 $ Status...40 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...41     : num [1:205] 7 7 6 NA 7 2 2 NA 1 1 ...
 $ CL...42     : num [1:205] 7 7 6 NA 7 3 1 NA 1 1 ...
 $ Status...43 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...44     : num [1:205] 7 7 6 NA 7 2 2 NA 1 1 ...
 $ CL...45     : num [1:205] 7 7 6 NA 7 3 1 NA 1 1 ...
 $ Status...46 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...47     : num [1:205] 6 7 5 NA 7 2 2 NA 1 1 ...
 $ CL...48     : num [1:205] 6 7 6 NA 7 3 1 NA 1 1 ...
 $ Status...49 : chr [1:205] "NF" "NF" "NF" NA ...
 $ PR...50     : num [1:205] 7 7 6 NA 7 2 1 NA 1 1 ...
 $ CL...51     : num [1:205] 7 7 4 NA 7 3 2 NA 1 1 ...
 $ Status...52 : chr [1:205] "NF" "NF" "PF" NA ...
 $ PR...53     : num [1:205] 7 7 4 NA 7 3 1 NA 1 1 ...
 $ CL...54     : num [1:205] 7 6 4 NA 7 2 3 NA 1 1 ...
 $ Status...55 : chr [1:205] "NF" "NF" "PF" NA ...
 $ PR...56     : num [1:205] 7 4 4 NA 6 3 1 5 1 1 ...
 $ CL...57     : num [1:205] 7 4 4 NA 4 3 3 5 1 1 ...
 $ Status...58 : chr [1:205] "NF" "PF" "PF" NA ...
 $ PR...59     : num [1:205] 6 4 7 NA 6 3 2 4 1 1 ...
 $ CL...60     : num [1:205] 6 3 6 NA 6 3 3 3 1 1 ...
 $ Status...61 : chr [1:205] "NF" "PF" "NF" NA ...
 $ PR...62     : num [1:205] 7 2 7 2 7 4 2 3 1 1 ...
 $ CL...63     : num [1:205] 7 4 6 1 7 3 3 4 1 1 ...
 $ Status...64 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...65     : num [1:205] 7 3 7 1 7 4 2 3 1 1 ...
 $ CL...66     : num [1:205] 7 4 7 1 7 3 3 4 1 1 ...
 $ Status...67 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...68     : num [1:205] 7 3 6 1 6 4 2 4 1 1 ...
 $ CL...69     : num [1:205] 7 4 6 1 6 3 3 4 1 1 ...
 $ Status...70 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...71     : num [1:205] 7 4 6 1 6 4 2 5 1 1 ...
 $ CL...72     : num [1:205] 7 4 6 1 6 3 3 4 1 1 ...
 $ Status...73 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...74     : num [1:205] 7 4 6 1 6 4 2 5 1 1 ...
 $ CL...75     : num [1:205] 7 4 6 1 6 3 3 4 1 1 ...
 $ Status...76 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...77     : num [1:205] 7 4 6 1 6 4 3 4 1 1 ...
 $ CL...78     : num [1:205] 7 5 5 1 6 3 3 4 1 1 ...
 $ Status...79 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...80     : num [1:205] 7 4 6 1 6 4 2 4 1 1 ...
 $ CL...81     : num [1:205] 7 5 5 1 6 3 3 4 1 1 ...
 $ Status...82 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...83     : num [1:205] 7 4 6 1 6 4 1 4 1 1 ...
 $ CL...84     : num [1:205] 7 5 5 1 6 2 2 4 1 1 ...
 $ Status...85 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...86     : num [1:205] 7 3 6 1 6 4 3 4 1 1 ...
 $ CL...87     : num [1:205] 7 4 5 1 6 2 3 4 1 1 ...
 $ Status...88 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...89     : num [1:205] 6 3 6 1 6 4 3 4 1 1 ...
 $ CL...90     : num [1:205] 6 3 5 1 5 2 3 4 1 1 ...
 $ Status...91 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...92     : num [1:205] 6 3 6 1 6 4 2 4 1 1 ...
 $ CL...93     : num [1:205] 6 3 5 1 5 2 2 4 1 1 ...
 $ Status...94 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...95     : num [1:205] 5 3 6 1 6 2 2 5 1 1 ...
 $ CL...96     : num [1:205] 6 3 5 1 5 2 2 4 1 1 ...
 $ Status...97 : chr [1:205] "NF" "PF" "NF" "F" ...
 $ PR...98     : num [1:205] 5 3 6 1 6 2 2 5 1 1 ...
 $ CL...99     : num [1:205] 5 3 5 1 5 2 2 4 1 1 ...
  [list output truncated]
dim(fh_na) 
[1] 205 133
  • 205カ国分、133の変数があることわかる
  • このデータはワイド形式なので、実際に分析する際には ロング形式に変換する必要がある
  • ただし、上記で扱った「世界銀行の各国の一人あたりGDPデータ」とは異なり、少々やっかい

やっかいな点

  1. 変数が国ごとに、1年度あたり 3 種類ある (PR, CL, Status)
    PR...2, CL...3, Status...4 は1972年のデータ
    PR...5, CL...6, Status...7 は1973年のデータ
    ・・・中略・・・
    PR...128, CL...129, Status...130は2015年のデータ
    PR...131, CL...132, Status...134 は2016年のデータ

  2. PR と CL が数量データで Status がカテゴリカルデータ
    ■ PRとCL = 数量データ (1 から 7)、Status = カテゴリカルデータ (F, PF, NF)

解決策:値を入れる変数を 2 つ (value, status) 作る
→ PR とCL の値は value、Status の値は status に入れる

  • 分析に先立ち、国名が書いてある左端の変数名が「1」になっている
  • 変数「1」は国名なので、rename() 関数を使って country という変数名に変更
fh_na <- fh_na %>% 
    rename(country = 1) # 「1」という変数名を「country」に変更
  • データ形式変更のイメージ図

  • 作業をやりやすく進めるため、2 つのデータフレーム (fh_country, fh_na) を作る
fh_country <- fh_na %>% 
  select(country)

fh_na <- fh_na %>% 
  select(-country)

fh_na の変数を確認

names(fh_na)
  [1] "PR...2"       "CL...3"       "Status...4"   "PR...5"       "CL...6"      
  [6] "Status...7"   "PR...8"       "CL...9"       "Status...10"  "PR...11"     
 [11] "CL...12"      "Status...13"  "PR...14"      "CL...15"      "Status...16" 
 [16] "PR...17"      "CL...18"      "Status...19"  "PR...20"      "CL...21"     
 [21] "Status...22"  "PR...23"      "CL...24"      "Status...25"  "PR...26"     
 [26] "CL...27"      "Status...28"  "PR...29"      "CL...30"      "Status...31" 
 [31] "PR...32"      "CL...33"      "Status...34"  "PR...35"      "CL...36"     
 [36] "Status...37"  "PR...38"      "CL...39"      "Status...40"  "PR...41"     
 [41] "CL...42"      "Status...43"  "PR...44"      "CL...45"      "Status...46" 
 [46] "PR...47"      "CL...48"      "Status...49"  "PR...50"      "CL...51"     
 [51] "Status...52"  "PR...53"      "CL...54"      "Status...55"  "PR...56"     
 [56] "CL...57"      "Status...58"  "PR...59"      "CL...60"      "Status...61" 
 [61] "PR...62"      "CL...63"      "Status...64"  "PR...65"      "CL...66"     
 [66] "Status...67"  "PR...68"      "CL...69"      "Status...70"  "PR...71"     
 [71] "CL...72"      "Status...73"  "PR...74"      "CL...75"      "Status...76" 
 [76] "PR...77"      "CL...78"      "Status...79"  "PR...80"      "CL...81"     
 [81] "Status...82"  "PR...83"      "CL...84"      "Status...85"  "PR...86"     
 [86] "CL...87"      "Status...88"  "PR...89"      "CL...90"      "Status...91" 
 [91] "PR...92"      "CL...93"      "Status...94"  "PR...95"      "CL...96"     
 [96] "Status...97"  "PR...98"      "CL...99"      "Status...100" "PR...101"    
[101] "CL...102"     "Status...103" "PR...104"     "CL...105"     "Status...106"
[106] "PR...107"     "CL...108"     "Status...109" "PR...110"     "CL...111"    
[111] "Status...112" "PR...113"     "CL...114"     "Status...115" "PR...116"    
[116] "CL...117"     "Status...118" "PR...119"     "CL...120"     "Status...121"
[121] "PR...122"     "CL...123"     "Status...124" "PR...125"     "CL...126"    
[126] "Status...127" "PR...128"     "CL...129"     "Status...130" "PR...131"    
[131] "CL...132"     "Status...133"

fh_country の変数を確認

names(fh_country)
[1] "country"
  • fh_na の変数をクリーニングする
colnames(fh_na) <- 
  str_replace_all(colnames(fh_na), 
                  c("\\.\\.\\." = "-")) %>% # 「・・・」を「-」と置き換える  
  str_subset("PR|CL|Status") %>%            # 変数名を「pr_1972」のように変更する  
  str_c(., "_") %>% 
  str_replace_all(c("-" =  "", 
                    "[0-9]" = "",
                    "PR" = "pr",          # pr を大文字に変更  
                    "CL" = "cl",          # cl を大文字に変更 
                    "Status" = "st")) %>% # st を Statys に変更 
  str_c(.,  rep(setdiff(1972:2016, 1981), # 1981年データを含めない
                each = 3))           # 年度ごとに3つ変数を作る
  • 確認する
names(fh_na)
  [1] "pr_1972" "cl_1972" "st_1972" "pr_1973" "cl_1973" "st_1973" "pr_1974"
  [8] "cl_1974" "st_1974" "pr_1975" "cl_1975" "st_1975" "pr_1976" "cl_1976"
 [15] "st_1976" "pr_1977" "cl_1977" "st_1977" "pr_1978" "cl_1978" "st_1978"
 [22] "pr_1979" "cl_1979" "st_1979" "pr_1980" "cl_1980" "st_1980" "pr_1982"
 [29] "cl_1982" "st_1982" "pr_1983" "cl_1983" "st_1983" "pr_1984" "cl_1984"
 [36] "st_1984" "pr_1985" "cl_1985" "st_1985" "pr_1986" "cl_1986" "st_1986"
 [43] "pr_1987" "cl_1987" "st_1987" "pr_1988" "cl_1988" "st_1988" "pr_1989"
 [50] "cl_1989" "st_1989" "pr_1990" "cl_1990" "st_1990" "pr_1991" "cl_1991"
 [57] "st_1991" "pr_1992" "cl_1992" "st_1992" "pr_1993" "cl_1993" "st_1993"
 [64] "pr_1994" "cl_1994" "st_1994" "pr_1995" "cl_1995" "st_1995" "pr_1996"
 [71] "cl_1996" "st_1996" "pr_1997" "cl_1997" "st_1997" "pr_1998" "cl_1998"
 [78] "st_1998" "pr_1999" "cl_1999" "st_1999" "pr_2000" "cl_2000" "st_2000"
 [85] "pr_2001" "cl_2001" "st_2001" "pr_2002" "cl_2002" "st_2002" "pr_2003"
 [92] "cl_2003" "st_2003" "pr_2004" "cl_2004" "st_2004" "pr_2005" "cl_2005"
 [99] "st_2005" "pr_2006" "cl_2006" "st_2006" "pr_2007" "cl_2007" "st_2007"
[106] "pr_2008" "cl_2008" "st_2008" "pr_2009" "cl_2009" "st_2009" "pr_2010"
[113] "cl_2010" "st_2010" "pr_2011" "cl_2011" "st_2011" "pr_2012" "cl_2012"
[120] "st_2012" "pr_2013" "cl_2013" "st_2013" "pr_2014" "cl_2014" "st_2014"
[127] "pr_2015" "cl_2015" "st_2015" "pr_2016" "cl_2016" "st_2016"
  • {tidyverse} パッケージの bind_cols() 関数を使って、fh_nafh_country の列 (country) を結合する
fh_na <- fh_country %>% # 
  bind_cols(fh_na)
  • マージしたデータフレーム fh_na を確認する
rmarkdown::paged_table(fh_na)
  • PRCL の値を入れる変数 (value) と PRCL を区別する変数 (type) を作る
PR_CL_long <- fh_na %>% 
  select(country,                         # country を選ぶ
         starts_with(c("pr", "cl"))) %>%  # pr と cl で初まる変数だけを選ぶ  
  pivot_longer(pr_1972:cl_2016,           # 変換したい変数の範囲を指定
               names_to = "type",         # 「変数名(pr_1972など)をtypeに入れる
               values_to = "value") %>%   # 「変数(pr_1972など) の値」をvalue に入れる
  separate(type,              
           into = c("type", "year"),      # typeの中身をtypeとyear2 つの変数に分ける  
           sep = "_")%>%              # typeの中身はpr_1973のように "_" で分けられている
           drop_na()                      # 欠損値 (na) を表示しない
ST_long <- fh_na %>% 
  select(country,                        # country を選ぶ
         starts_with("st")) %>%          # st で初まる変数だけを選ぶ
  pivot_longer(st_1972:st_2016,          # 変換したい変数の範囲を指定
               names_to = "name",        # 「変数名(st_1972など)をnameに入れる
               values_to = "status") %>% # 「変数(st_1972など) の値」をstatusに入れる
  separate(name, 
           into = c("name", "year"),     # nameの中身(st_1972など)をnameとyear 2 つの変数に分ける
           sep = "_") %>%               # nameの中身はst_1972のように "_" で分けられている
  select(-name)%>%                       # nameは不要なので削除  
  drop_na()                              # 欠損値 (na) を省く
  • PR_CL_long を確認する  
names(PR_CL_long)
[1] "country" "type"    "year"    "value"  
  • ST_long を確認する  
names(ST_long)
[1] "country" "year"    "status" 
  • {tidyverse} パッケージの left_joint() 関数を使って、共通する2 つの変数( countryyear)を手がかりとして PR_CL_longST_long を列方向に結合する
fh_all_long <- PR_CL_long %>% 
  left_join(ST_long, 
            by = c("country", "year"))
DT::datatable(fh_all_long)
  • ロング形式に変換されたデータを使うと様々な分析が可能になる

2.3 データの可視化 (Freedom House)

北朝鮮と韓国の政治的な権利 (PR) の推移
- 例えば、北朝鮮と韓国の政治的な権利 (PR) の推移 (1972-2016) を可視化してみる

korea_PR <- fh_all_long %>% 
  filter(country == "North Korea" | country == "South Korea") %>% 
  filter(type == "pr")
korea_PR %>% 
  ggplot(aes(x = value, y = year, 
             color = country,
             shape = country)) +
  geom_point() +
  ggtitle("北朝鮮と韓国の政治的な権利: 1972-2016") +
  labs(x = "良い ← 政治的な権利 → 悪い", y = "Year") +
  theme(legend.position = c(0.5, 0.8)) 

  • 北朝鮮の政治的な権利 (PR) は1972年以来、一環して「7」(=政治的な権利スコアーは最悪)
  • 韓国の政治的な権利 (PR) は1972年の頃は「5」だったが、1988年以降「2 or 1」(スコア = 1 は政治的な権利は最善)と状況は改善している   

中国と日本の政治的な権利 (PR) の推移
- 例えば、中国と日本の政治的な権利 (PR) の推移 (1972-2016) を可視化してみる

jpn.chi_PR <- fh_all_long %>% 
  filter(country == "Japan" | country == "China") %>% 
  filter(type == "pr")
jpn.chi_PR %>% 
  ggplot(aes(x = value, y = year, 
             color = country, 
             shape = country)) +
  geom_point() +
  ggtitle("中国と日本の政治的な権利: 1972-2016") +
  labs(x = "良い ← 政治的な権利 → 悪い", y = "Year") +
  theme(legend.position = c(0.5, 0.8)) 

  • 中国の政治的な権利 (PR) は1972年以来、一環して「7 =政治的な権利スコアーは最悪、もしくは 6)
  • 日本の政治的な権利 (PR) は1980年以来、ほぼ一環して「1 = 政治的な権利スコアーは最善」
参考文献
  • Tidy Animated Verbs
  • 宋財泫 (Jaehyun Song)・矢内勇生 (Yuki Yanai)「私たちのR: ベストプラクティスの探究」
  • 宋財泫「ミクロ政治データ分析実習(2022年度)」
  • 土井翔平(北海道大学公共政策大学院)「Rで計量政治学入門」
  • 矢内勇生(高知工科大学)授業一覧
  • 浅野正彦, 矢内勇生.『Rによる計量政治学』オーム社、2018年
  • 浅野正彦, 中村公亮.『初めてのRStudio』オーム社、2018年
  • Winston Chang, R Graphics Cookbook, O’Reilly Media, 2012.
  • Kieran Healy, DATA VISUALIZATION, Princeton, 2019
  • Kosuke Imai, Quantitative Social Science: An Introduction, Princeton University Press, 2017