第10回 データ・ハンドリング(2)
関西大学総合情報学部
2024-06-13
すぐに実習できるように準備しておきましょう。
Data
フォルダーを作成し、そこにアップロードしましょう。例) 大陸ごとに政治的権利(FH_PR
)と市民的自由(FH_CL
)の平均値を計算する
# A tibble: 5 × 3
Continent PR CL
<chr> <dbl> <dbl>
1 Africa 15.8 25.8
2 America 29.4 42.6
3 Asia 14.7 24.2
4 Europe 31.9 47.6
5 Oceania 31.8 47.2
変数が持つ情報を要約した数値
元の情報:
summarise()
の使い方summarise()
: 記述統計量を計算する{dplyr}の関数
記述統計の関数の例
mean()
:平均値median()
:中央値sd()
:不偏分散の平方根(一般的に「標準偏差」と呼ばれるもの)var()
:不偏分散IQR()
:四分位範囲min()
、max()
:最小値と最大値n()
:ケース数(引数不要)例) df
のPopulation
とArea
の平均値(mean()
)を計算
summarise()
内に異なる関数を使うことも可能
例) df
のPopulation
とArea
の平均値(mean()
)と標準偏差(sd()
)を計算
summarise()
内に出力される結果の列名 = 関数()
を指定
例) df
のPopulation
とArea
の平均値(mean()
)と標準偏差(sd()
)を計算し、結果の列名をMean_Pop
、SD_Pop
などとする
{dplyr}のgroup_by()
を使用
例) df
のContinent
でデータをグループ化し、PPP_per_capita
の平均値を計算
例) df
のContinent
とG20
でデータをグループ化し、HDI_2018
の平均値を計算
`summarise()` has grouped output by 'Continent'. You can override using the
`.groups` argument.
# A tibble: 10 × 3
# Groups: Continent [5]
Continent G20 Mean_HDI
<chr> <dbl> <dbl>
1 Africa 0 0.550
2 Africa 1 0.705
3 America 0 0.727
4 America 1 0.84
5 Asia 0 0.710
6 Asia 1 0.798
7 Europe 0 0.859
8 Europe 1 0.877
9 Oceania 0 0.729
10 Oceania 1 0.938
summarise()
謎のメッセージが出力される
## `summarise()` has grouped output by 'Continent'. You can override using
the `.groups` argument.
とりあえず、group_by()
の後にsummarise()
を使う場合、summarise()
の最後に.groups = "drop"
を追加する。
quantile()
など)を使う場合、問題が生じる可能性あり
summarise()
の後に更にパイプ(|>
)を使って計算を続ける場合.groups = "drop"
をしておけば安全summarise()
の代わりにreframe()
を使えば.groups = "drop"
は不要({dplyr} 1.1.0から).groups = "drop"
を追加する謎のメッセージが出力されなくなる
df |>
group_by(Continent, G20) |>
summarise(Mean_HDI = mean(HDI_2018, na.rm = TRUE),
.groups = "drop")
# A tibble: 10 × 3
Continent G20 Mean_HDI
<chr> <dbl> <dbl>
1 Africa 0 0.550
2 Africa 1 0.705
3 America 0 0.727
4 America 1 0.84
5 Asia 0 0.710
6 Asia 1 0.798
7 Europe 0 0.859
8 Europe 1 0.877
9 Oceania 0 0.729
10 Oceania 1 0.938
summarise()
の中にn()
を使用
df |>
group_by(Continent) |>
summarise(Mean_PPP = mean(PPP_per_capita, na.rm = TRUE),
SD_PPP = sd(PPP_per_capita, na.rm = TRUE),
Cases = n())
# A tibble: 5 × 4
Continent Mean_PPP SD_PPP Cases
<chr> <dbl> <dbl> <int>
1 Africa 5667. 6015. 54
2 America 18100. 12601. 36
3 Asia 22728. 24067. 42
4 Europe 37783. 21276. 50
5 Oceania 27573. 21984. 4
across()
関数を利用: 詳細は教科書第14.1章を参照
例) df
のPopulation
からPPP
列まで平均値と標準偏差を計算し、結果の変数名は元の変数名_Mean
、元の変数名_SD
とする
df |>
summarise(across(Population:PPP,
.fns = list(Mean = ~mean(.x, na.rm = TRUE),
SD = ~mean(.x, na.rm = TRUE))))
# A tibble: 1 × 8
Population_Mean Population_SD Area_Mean Area_SD GDP_Mean GDP_SD PPP_Mean
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 41737773. 41737773. 696069. 696069. 473031. 473031. 717953.
# ℹ 1 more variable: PPP_SD <dbl>
mutate()
: データフレームの変数を用いた計算を行い、新しい列として追加
例) df
のPopulation
をArea
で割り(=人口密度)、Density
という名の列として追加する
例) df
のPopulation
をArea
で割り(人口密度)、Density
という名の列として追加する
# A tibble: 186 × 19
Country Population Area GDP PPP GDP_per_capita PPP_per_capita G7
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Afghanis… 38928346 6.53e5 1.91e4 82737. 491. 2125. 0
2 Albania 2877797 2.74e4 1.53e4 39658. 5309. 13781. 0
3 Algeria 43851044 2.38e6 1.70e5 496572. 3876. 11324. 0
4 Andorra 77265 4.7 e2 3.15e3 NA 40821. NA 0
5 Angola 32866272 1.25e6 9.46e4 218533. 2879. 6649. 0
# ℹ 181 more rows
# ℹ 11 more variables: G20 <dbl>, OECD <dbl>, HDI_2018 <dbl>,
# Polity_Score <dbl>, Polity_Type <chr>, FH_PR <dbl>, FH_CL <dbl>,
# FH_Total <dbl>, FH_Status <chr>, Continent <chr>, Density <dbl>
mutate()
内に.after
、または.before
を指定
relocate()
関数と同じ仕組み(第9回)例) Population
をArea
で割り、Density
という名の新しい列Area
の後に追加する。
# A tibble: 186 × 19
Country Population Area Density GDP PPP GDP_per_capita
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Afghanistan 38928346 652860 59.6 1.91e4 8.27e4 491.
2 Albania 2877797 27400 105. 1.53e4 3.97e4 5309.
3 Algeria 43851044 2381740 18.4 1.70e5 4.97e5 3876.
4 Andorra 77265 470 164. 3.15e3 NA 40821.
5 Angola 32866272 1246700 26.4 9.46e4 2.19e5 2879.
6 Antigua and Barbuda 97929 440 223. 1.73e3 2.08e3 17643.
7 Argentina 45195774 2736690 16.5 4.50e5 1.04e6 9949.
8 Armenia 2963243 28470 104. 1.37e4 3.84e4 4614.
9 Australia 25499884 7682300 3.32 1.39e6 1.28e6 54615.
10 Austria 9006398 82409 109. 4.46e5 5.03e5 49555.
# ℹ 176 more rows
# ℹ 12 more variables: PPP_per_capita <dbl>, G7 <dbl>, G20 <dbl>, OECD <dbl>,
# HDI_2018 <dbl>, Polity_Score <dbl>, Polity_Type <chr>, FH_PR <dbl>,
# FH_CL <dbl>, FH_Total <dbl>, FH_Status <chr>, Continent <chr>
各国が世界人口に占める割合を計算し、降順で出力
df
のPopulation
の合計をTotal_Pop
という列として追加する。Population
をTotal_Pop
で割り、100を掛ける。結果はShare_Pop
という名の列としてPopulation
後に追加する。Country
からShare_Pop
までの列のみ残す。Total_Pop
列を除外する。Share_Pop
が大きい順で行を並び替えるdf |>
# Total_Popを作らずにShare_Pop作成時に直接sum(Population)を入れてもOK
mutate(Total_Pop = sum(Population),
Share_Pop = Population / Total_Pop * 100,
.after = Population) |>
select(Country:Share_Pop) |>
select(!Total_Pop) |>
arrange(desc(Share_Pop))
# A tibble: 186 × 3
Country Population Share_Pop
<chr> <dbl> <dbl>
1 China 1447470092 18.6
2 India 1380004385 17.8
3 United States 334308644 4.31
4 Indonesia 273523615 3.52
5 Pakistan 220892340 2.85
6 Brazil 212559417 2.74
7 Nigeria 206139589 2.66
8 Bangladesh 164689383 2.12
9 Russia 145934462 1.88
10 Mexico 128932753 1.66
# ℹ 176 more rows
G7、G20、OECDのいずれかに加盟している国を「先進国」、それ以外は「その他」とし、二つのグループの人口密度、人間開発指数、民主主義度の平均値を出力する。
df
を利用するDeveloped
という列を追加し、G7
、G20
、OECD
のいずれかに加盟した国なら"先進国"
、それ以外なら"その他"
とする。Density
という名の列として追加する。HDI_2018
とPolity_Score
のいずれかが欠損した行を除外する。Developed
変数でデータをグルーピングする。HDI_2018
、Polity_Score
、Density
の平均値を求める。df2
という名前のオブジェクトとして作業環境内に格納する。df2 <- df |>
mutate(Developed = G7 + G20 + OECD,
Developed = if_else(Developed > 1, "先進国", "その他"), # 上書き
Density = Population / Area) |>
# filter()の代わりにdrop_na(HDI_2018, Polity_Score) もOK
filter(!is.na(HDI_2018), !is.na(Polity_Score)) |>
group_by(Developed) |>
summarise(Density = mean(Density),
HDI = mean(HDI_2018),
Polity = mean(Polity_Score))
df2
# A tibble: 2 × 4
Developed Density HDI Polity
<chr> <dbl> <dbl> <dbl>
1 その他 197. 0.695 3.92
2 先進国 174. 0.892 7.91
summarise()
の結果を並び替えたいdf2
を"先進国"
> "その他"
の順番で表示させたい。
summarise()
を行う場合、グルーピング変数のアルファベット順で表示される。summarise()
の前にグルーピング変数をFactor型に変換する必要がある。
Developed
をFactor型にDeveloped
列をfactor化し、要素の順番は"先進国"
、"その他"
の順にする。
levels
で指定した順番df |>
mutate(Developed = G7 + G20 + OECD,
Developed = if_else(Developed > 1, "先進国", "その他"),
Developed = factor(Developed, levels = c("先進国", "その他")),
Density = Population / Area) |>
filter(!is.na(HDI_2018), !is.na(Polity_Score)) |>
group_by(Developed) |>
summarise(Density = mean(Density),
HDI = mean(HDI_2018),
Polity = mean(Polity_Score))
# A tibble: 2 × 4
Developed Density HDI Polity
<fct> <dbl> <dbl> <dbl>
1 先進国 174. 0.892 7.91
2 その他 197. 0.695 3.92
mutate()
内にif_else()
を使用
df
のOECD
が1
なら"OECD加盟国"
、それ以外なら"OECD非加盟国"
に変換し、OECD_J
という列として追加例) 変換前
例) 変換後
df |>
mutate(OECD_J = if_else(OECD == 1, "OECD加盟国", "OECD非加盟国")) |>
group_by(OECD = OECD_J) |> # 「=」で列名の変更が可能
summarise(PPP = mean(PPP_per_capita, na.rm = TRUE),
HDI = mean(HDI_2018, na.rm = TRUE),
FH = mean(FH_Total, na.rm = TRUE))
# A tibble: 2 × 4
OECD PPP HDI FH
<chr> <dbl> <dbl> <dbl>
1 OECD加盟国 46000. 0.894 89.1
2 OECD非加盟国 14229. 0.667 49.9
mutate()
内にcase_when()
を使用
.default = 新しい値
は「上記の条件全てが満たされない場合の値」を意味する。例) df
のContinent
を日本語にし、Continent_J
として追加
df |>
mutate(Continent_J = case_when(Continent == "Africa" ~ "アフリカ",
Continent == "America" ~ "アメリカ",
Continent == "Asia" ~ "アジア",
Continent == "Europe" ~ "ヨーロッパ",
.default = "オセアニア")) |>
group_by(大陸 = Continent_J) |>
# 日本語は非推奨だが、一応使える(_と.を除く特殊記号不可)
summarise(OECD加盟国比率 = mean(OECD),
国家数 = n())
# A tibble: 5 × 3
大陸 OECD加盟国比率 国家数
<chr> <dbl> <int>
1 アジア 0.0714 42
2 アフリカ 0 54
3 アメリカ 0.139 36
4 オセアニア 0.5 4
5 ヨーロッパ 0.54 50
例) Continent
がAP
列を追加し、"Asia"
か"Oceania"
、"America"
なら1、以外は0
方法1:if_else()
の利用
方法2:case_when()
の利用
方法3:case_when()
+ %in%
の利用
NA
ではない欠損値もあることに注意世論調査などの場合、欠損値がNA
でなく、9
や99
、""
などの場合があるため、自分でNA
に変換する必要があるケースも多い。
my_data
の例
YoungAge
変数を作成し、Age
が39以下なら1
、それ以外は0
にする。
HighEduc2
変数を作成し、HighEduc
が1なら"大卒以上"
、それ以外は"大卒未満"
にする。
NA
を指定(if_else()
も同様)my_data |>
mutate(YoungAge = case_when(Age == 999 ~ NA,
Age <= 39 ~ 1,
.default = 0),
HighEduc2 = case_when(HighEduc >= 8 ~ NA,
HighEduc == 1 ~ "大卒以上",
.default = "大卒未満"))
# A tibble: 10 × 5
ID Age HighEduc YoungAge HighEduc2
<int> <dbl> <dbl> <dbl> <chr>
1 1 32 1 1 大卒以上
2 2 35 0 1 大卒未満
3 3 57 0 0 大卒未満
4 4 999 1 NA 大卒以上
5 5 74 0 0 大卒未満
6 6 66 9 0 <NA>
7 7 999 1 NA 大卒以上
8 8 49 1 0 大卒以上
9 9 78 8 0 <NA>
10 10 67 9 0 <NA>
特定の値を欠損値とし、それ以外の値は元も値にする場合
if_else()
を使用し、条件に合致した場合はNA
を、合致しない場合は元の変数のままにする。if_else()
でなく、case_when()
を使うことも可能
case_when()
を使うか、OR演算子(|
/ %in%
)を用いたif_else()
を使用する。{naniar}パッケージのreplace_with_na()
関数を利用
変数名 = 欠損値の値
変数名 = c(値1, 値2, ...)
na_if()
関数mutate()
における複数の処理同じ内容のコードであるため、好きな書き方で問題ないが、まとめた方が効率的
mutate()
内に2つの処理mutate()
内に1つの処理