--- title: "統計データ解析I" subtitle: "第4講 練習問題 解答例" date: "`r Sys.time()`" format: html: toc: true html-math-method: katex self-contained: true grid: margin-width: 350px execute: echo: true warning: false reference-location: margin citation-location: margin tbl-cap-location: margin fig-cap-location: margin editor: visual editor_options: chunk_output_type: console --- ## 準備 以下で利用する共通パッケージを読み込む. ```{r} library(conflicted) # 関数名の衝突を警告 conflicts_prefer( # 優先的に使う関数を指定 dplyr::filter(), dplyr::select(), dplyr::lag(), ) library(tidyverse) ``` ## データフレームの操作 ### 問題 `datasets::airquality` に対して以下の条件を満たすデータを取り出しなさい. - 7月のオゾン濃度 (`Ozone`) - 風速 (`Wind`) が時速10マイル以上で,かつ気温 (`Temp`) が華氏80度以上の日のデータ - オゾン (`Ozone`) も日射量 (`Solar.R`) も欠測 (`NA`) でないデータの月 (`Month`) と日 (`Day`) ### 解答例 `datasets::airquality` を `tibble` 形式に変換する. ```{r} aq_tbl <- as_tibble(airquality) # tibble 形式へ変換 ``` 7月のオゾン濃度のデータを取り出す. ```{r} aq_tbl |> filter(Month == 7) |> # Month %in% 7 などとしても良い select(Ozone) ``` 風速時速10マイル以上かつ気温が華氏80度以上のデータを取り出す. ```{r} aq_tbl |> filter(Wind >= 10 & Temp >= 80) ``` 日射量が欠測でないデータの月と日を取り出す. ```{r} aq_tbl |> filter(!is.na(Ozone) & !is.na(Solar.R)) |> select(Month,Day) # 書いた順に並ぶ aq_tbl |> filter(!is.na(Ozone) & !is.na(Solar.R)) |> select(Month:Day) # もともと並んでいるので c(Month,Day) と同じ ``` ## データの読み込みと操作 ### 問題 サンプルデータ (`jpdata`) を読み込んで操作しなさい. ::: callout-note より取得したデータ (文字コード : utf8) - jpdata1.csv : 県別の対象データ - jpdata2.csv : 対象データの内容説明 - jpdata3.csv : 県と地域の対応関係 (地域から探す / 全県を選択 / 項目を選択してダウンロード) ::: - 作業ディレクトリ内にサブディレクトリ `data` を作成し,その中に置いて読み込む. ```{r} #| eval: false jp_data <- read_csv(file = "data/jpdata1.csv") jp_item <- read_csv(file = "data/jpdata2.csv") jp_area <- read_csv(file = "data/jpdata3.csv") ``` 日本語に問題がある場合は英語版を読み込む. ```{r} #| eval: false jp_data_en <- read_csv(file = "data/jpdata1-en.csv") jp_area_en <- read_csv(file = "data/jpdata3-en.csv") ``` ### 解答例 ファイルからデータを読み込む. ```{r} jp_data <- read_csv(file = "data/jpdata1.csv") jp_item <- read_csv(file = "data/jpdata2.csv") jp_area <- read_csv(file = "data/jpdata3.csv") ``` ::: callout-note 文字コードは関数 `readr::guess_encoding()` により推測される. ```{r} #| eval: false guess_encoding("data/jpdata1.csv") ``` ::: 以下にデータ操作の例を示す. ```{r} #' 項目名の内容を確認 jp_item #' 最初の10県を表示 head(jp_data, n = 10) #' 最後の10県を表示 tail(jp_data, n = 10) #' 地方名を確認 View(jp_area) # 左上ペインに表として表示される #' 人口の最大値を見る with(jp_data, max(人口)) #' どの都道府県の人口多いか調べる ('?which.max' を参照) with(jp_data, which.max(人口)) # 行番号が返る jp_data[with(jp_data, which.max(人口)),] #' 行を抽出するには関数 dplyr::filter() を使うのが簡単 jp_data |> filter(人口 == max(人口)) #' 人口の多い順に都道府県を並べる ('?order' を参照) with(jp_data, order(人口, decreasing = TRUE)) # 行番号を取得 jp_data[with(jp_data, order(人口, decreasing = TRUE)),] # 並べ替え with(jp_data, 県名[order(人口, decreasing = TRUE)]) # 県名のみを表示 #' 行を並べ替えるには関数 dplyr::arrange() を使うのが簡単 jp_data |> arrange(desc(人口)) |> print(n = Inf) # ('?dplyr::desc' を参照) ``` 上記と同じ内容を英語版のデータで実行する場合は以下のようになる. ```{r} jp_data_en <- read_csv(file="data/jpdata1-en.csv") jp_area_en <- read_csv(file="data/jpdata3-en.csv") #' データを確認する head(jp_data_en, n = 10) tail(jp_data_en, n = 10) View(jp_area_en) #' 人口の最大値を見る with(jp_data_en, max(population)) #' 人口の最大値を与える県の番号を見る with(jp_data_en, which.max(population)) #' どの都道府県の人口多いか調べる jp_data_en |> filter(population == max(population)) #' 人口の多い順に都道府県を並べる jp_data_en |> arrange(desc(population)) |> View() ``` ## データの集計 ### 問題 以下の指示に従ってサンプルデータ (`jpdata`) を整理しなさい. - 県別の人口密度を求めよ. - 地方別の人口密度を求めよ. ::: callout-warning 県ごとに人口が異なるので単純に人口密度を平均してはいけない. ::: - 地方別の1000人当たりの婚姻・離婚数を概算せよ. なお,データの記述では「人口1000人当たり」とあるが,この「人口」とは若年層は婚姻不可として除いた「婚姻可能な人口1000人当たり」と考えて計算しなさい. ### 解答例 県別の人口密度 (人口/面積) を求める. ```{r} with(jp_data, 人口/面積) # 値のみ返す ``` 都道府県別の人口密度を求める. ```{r} jp_data |> select(県名, 人口, 面積) |> # 県名,人口,面積を選択 mutate(人口密度 = 人口/面積) # 人口密度を計算 ``` 地方別の人口密度 (地方の総人口/地方の総面積) を求める. ```{r} jp_data |> mutate(地方 = as_factor(jp_area[["地方"]])) |> # 地方の情報を付加 group_by(地方) |> # 地方ごとにグループ化 summarize((across(c(人口, 面積), sum))) |> # 地方ごとに人口と面積を集計 mutate(人口密度 = 人口/面積) # 地方別の人口密度を計算 ``` 地方別の婚姻・離婚数(1000人あたり)を求める. ```{r} jp_data |> mutate(婚姻可能 = 人口-若年, # 婚姻可能な人口を推計 婚姻数 = 婚姻可能*婚姻/1000, # 婚姻数/1000人から人数を推計 離婚数 = 婚姻可能*離婚/1000, # 離婚数/1000人から人数を推計 地方 = as_factor(jp_area[["地方"]])) |> # 地方の情報を付加 group_by(地方) |> # 地方ごとにグループ化 summarize((across(婚姻可能:離婚数, sum))) |> # 地方別の合計を計算 mutate(婚姻 = 婚姻数/婚姻可能*1000, # 1000人あたりの婚姻数を計算 離婚 = 離婚数/婚姻可能*1000) # 1000人あたりの離婚数を計算 ``` ::: callout-tip 日本語の扱いで不具合がある場合は - jp_data -\> jp_data_en - 人口 -\> population - 若年 -\> young_population - 婚姻 -\> marriage - 離婚 -\> divorce など書き換えて試してみて下さい. :::