9章 tidyrによるデータの整理
9.0 ライブラリーの読み込み
library("tidyverse")9.1 はじめに
9.2 整理データ
練習問題1 例に上げた表について、変数と観測値がどのように組織されているか答えなさい。
各行は(国、年)の組み合わせを表します。列casesとpopulationは、それらの変数の値を含みます。いわゆるtidyな形式です。
table1
# A tibble: 6 x 4
country year cases population
<chr> <int> <int> <int>
1 Afghanistan 1999 745 19987071
2 Afghanistan 2000 2666 20595360
3 Brazil 1999 37737 172006362
4 Brazil 2000 80488 174504898
5 China 1999 212258 1272915272
6 China 2000 213766 1280428583各行は(国、年、タイプ)の組み合わせを表します。countには、各typeの値を含みます。
各行は(国、年)の組み合わせを表します。カラムは、casesとpopulationの値を文字列として持つrateがあります。
変数ごとに表が分かれています。この表table4aにはcasesがtable4bにはpopulationの値が含まれています。日本のお役所のデータによく見られる形式で、人間には見やすいが、機械には読みにくい形式です。
練習問題2 table2とtable4a+table4bについてrateを計算しなさい。下記、4つの操作を実行する必要がある。どの表現が最も簡単で、どれが一番難しいか?
table2とtable4a+table4bについてrateを計算しなさい。下記、4つの操作を実行する必要がある。どの表現が最も簡単で、どれが一番難しいか?国ごとの年間の結核の症例数を抽出します。
1年ごとに国ごとに一致する人口を抽出します。
ケースを母集団で割り、10000を掛けます。
適切な場所に戻して保管してください。
本来はこのように加工したいですね。spread()を使い、素直にカラムを横に展開すれば3行で計算できます。以下は、あまり推奨されない加工です。
1人当たりの症例数を計算するには、国と年の単位で、症例数を人口で割る必要があるので、そこを目標にtable2を加工します。table2を分割してbind_cols()で結合し直してますが、このような簡単にデータを揃えられない場合もビジネスのデータでは多いので、その際は**_join()を使ったほうがいいと思います。**_join()はデータが多くなると、検索で処理が重くなるので、その点はトレードオフです。
tablea4aとtable4bを使う方はこのような感じでしょうか。わざと%>%と{dplyr}を使っているのでくどいですね。このように計算するのであれば、{dplyr}は使わないほうが簡潔かもしれません。
練習問題3 table1の代わりにtable2を使用して、casesの時系列プロットを再作成しなさい。
table1の代わりにtable2を使用して、casesの時系列プロットを再作成しなさい。
9.3 広げたり集めたり
練習問題1 gather()とspread()はなぜ対象ではないのか。
gather()とspread()はなぜ対象ではないのか。gather()を適用する際に、列のデータ型の情報が失われます。その点で対象ではありません。
convert = TRUEを設定すれば、ベクトルを適切な型に変換してれますが、この変換は単に変数の型を推測しているだけなので、常に元の変数型を返すわけではありません。
練習問題2 このコードが失敗するのはなぜですか?
データフレームから変数を選択するとき、gather()は1999や2000のような数を列番号として解釈します。この場合、gather()はデータフレームの1999番目と2000番目の列を選択しようとします。1999と2000のような非構文変数名を選択するには、名前をバッククォート(`)で囲むか、文字列として指定します。
練習問題3 なぜこのtibbleを広げると失敗するのでしょうか。
tibbleを広げると失敗するのでしょうか。spread()でkeyを展開した際に、1行目と3行目のPhillip Woodsのageを一意に特定できないので、どちらの行にvalueが入れば適切なのか判別できません。
このような場合は、一意に特定するための複合主キーを作成します。
練習問題4 このtibbleを整理しなさい。
tibbleを整理しなさい。こんな感じにtidyにするのはどうでしょうか。
9.4 分割と接合
練習問題1 separate()のextraとfillは何をするのでしょうか。
separate()のextraとfillは何をするのでしょうか。separate()のextra = "drop"はカラムが不足している場合、その値をドロップします。
separate()のextra = "merge"はカラムが不足している場合、その値を残します。
この例では、2行目の要素が少ないため、NAが発生します。
separate()のfill = "right"は要素が少ない場合、どちらから値を埋めるかを設定できます。
練習問題2 unite()とseparate()には、引数removeがあります。それは何をするためのものか?
unite()とseparate()には、引数removeがあります。それは何をするためのものか?デフォルトでは、remove = TRUEとなっており、結合または分割の対象カラムを残すかどうかを設定できます。
練習問題3 separate()とextract()を比較しなさい。
separate()とextract()を比較しなさい。extract()は正規表現を使用して文字ベクトル内のグループを指定し、その単一文字ベクトルを複数の列に分割します。separate()と比べると、共通の区切り記号や特定の列位置を必要としないので、柔軟です。
9.5 欠損値
練習問題1 fill引数をspread()やcomplete()で比較しなさい。
fill引数をspread()やcomplete()で比較しなさい。spread()のfillは、特定の値で欠損値を補完することが可能です。
complete()のfillは、特定の値をリストで指定し、欠損値を補完することが可能です。
練習問題2 fill()の.dirctionは何をするのか。
fill()の.dirctionは何をするのか。fill()の.directionは、欠損値をレコードの上の値を使って補完するのか、下の値を使って補完するのかを設定します。
9.6 ケーススタディ
この章で使われているコードを先に実行しておきます。
練習問題1 このケーススタディでは欠損値をna.rm = TRUEで削除したが、これは妥当か。
na.rm = TRUEで削除したが、これは妥当か。妥当かどうかの判断はデータから判断できるのかもしれません。0自体はデータに含まれているので、欠損値は結核が0件ということを意味するのではなく、データが取得できない欠損といえます。なので、欠損値を除外しても良いのではないでしょうか。
また、欠損値として認識できる行もありますが、全ての国で、全ての年代があるわけでないようです。なので暗黙的な欠損がデータ自体に存在しています。
調べてみると、たくさんの国のデータが暗黙的に欠損しているというよりも、特定の国のデータがごそっと抜けていてるようですね。
練習問題2 mutate(key = str_replace(key, "newrel", "new_rel")を無視するとどうなるのか。
mutate(key = str_replace(key, "newrel", "new_rel")を無視するとどうなるのか。separate()は、分割後の要素が少ないというエラーが発生します。
練習問題3 iso2、iso3がcountryと重複していたが、これを確認しなさい。
iso2、iso3がcountryと重複していたが、これを確認しなさい。group_by()の単位にcountryをいれても入れなくてもカーディナリティは変わりません。なので、countryとiso2 or iso3は同じような値を持っています。
練習問題4 各国、年、性別について結核の総症例数を計算し、可視化しなさい。
国の数を考えるとファセットや色分けは難しいので、一旦国ごとに男女でわけで時系列推移を確認します。特定の年代にスパイクが確認できます。

性別に関わらず、総結核数が多い上位10カ国を抜き出して見てみます。インドと中国の増加の仕方は異なります。インドは突発的に結核が増えた一方で、中国は増加したまま結核数が減少していないようです。

9.7 非整理データ
最終更新
役に立ちましたか?