joinでテーブル結合(3).R
要約
・膨大なデータを結合するときは、予め数を絞ってから
・列を指定して絞る:SELECT()、行を指定して絞る:select()
・条件式で行を絞る:filter()、トップNで行を絞る:top_n()
効率的に作業するなら予めデータを絞ろう
いくら*_join()たちが自動でjoinしてくれるとはいっても、10万件のデータをjoinするのはさすがにダルい。待ってる時間にコーヒーでも淹れようかなと戻ってきても、まだjoinしてる最中だったりする。ちなみにコーヒーは家でも会社でもよく飲んでいる。常飲。
さて、実際のところ昨今はデータがサーバー上に置いてあることがほとんどで、弊社のように回線が細いとそっちがボトルネックになってしまう。ダウンロード量を減らすために使えるとよいのだけれど、ここで扱うのは、あくまでもダウンロードした後のデータに対してjoin前に加える前処理だけだ。ダウンロード量を減らしたいなら、まじめにSQL文を書きましょう。
必要な部分に絞り込む
なんだかんだで、分析目的や方法にメドがついていることは多い。
例えばX年からY年までの予算消費を分析するなら、予算金額と消費年月と科目etc.が最低限必要だとか、科目コードと科目名の一覧であるマスタが欲しいとか、予算テーブルと消費テーブルが別だから何をキーとして結合したらよいだろうとか、そういうことが分かっている。
いや、分かっているは言い過ぎた。現在の作業者は知らなくて、はるか昔に方法を決めた人だけが知っていて墓場に持って行ってしまったということは稀によくある。
それはともかく、分析するときには目的や方法に合わせて、どの列が必要なのかが決まる。また、先ほどの消費年月などのように期間=行を絞るということもされる。
つまり、データ全体の中から必要な部分を決めることができるので、絞り込んでデータ量を削減することができる。
列を指定するselect()、行を指定するslice()
まずはselect()。どの列を使いたいのか、列名で指定したり何列目かで指定したりできる。指定の方法は実例で見た方が早い。
今回のようなデータセットの場合、社員と1対1で対応する社員ID(NO)と、マスタを使って名前に置き換えたい部署コード(ShoCo、Kibo)があれば用は足りるわけで、joinに対して何の仕事もしていないSEX・AGEは省略してもよい(し、人事マスタのようなもので分離されているのが普通なので、必要に応じて改めてNOをキーとしてjoinすればよい。)
> select(x, NO, ShoCo, Kibo)
NO ShoCo Kibo
1 1 1 2
2 2 3 6
3 3 4 3
4 4 5 1
5 5 5 4
6 6 3 1
> select(x, c(NO, ShoCo, Kibo))
NO ShoCo Kibo
1 1 1 2
2 2 3 6
3 3 4 3
4 4 5 1
5 5 5 4
6 6 3 1
> select(x, 1, 4, 5)
NO ShoCo Kibo
1 1 1 2
2 2 3 6
3 3 4 3
4 4 5 1
5 5 5 4
6 6 3 1
select()ではさらに列を検索して指定するようなことができる。バリエーションが充実しており、下記記事が詳しい。
一方、行を指定することもできる。それがslice()だ。これも実例を見た方が早い。行番号で行を指定している。
> slice(x, 2, 3, 5)
NO SEX AGE ShoCo Kibo
1 2 男 28 3 6
2 3 女 27 4 3
3 5 女 24 5 4
> slice(x, 2:3, 5)
NO SEX AGE ShoCo Kibo
1 2 男 28 3 6
2 3 女 27 4 3
3 5 女 24 5 4
> slice(x, c(2:3, 5))
NO SEX AGE ShoCo Kibo
1 2 男 28 3 6
2 3 女 27 4 3
3 5 女 24 5 4
>
条件式で絞るfilter()、トップNで絞るtop_n()
例えば、男性だけ・女性だけを解析したいときに使えるのがfilter()だ。
slice()は行番号が分からないと絞り込めないが、分析対象にしたいデータがどの行にあるかというのは分からないことが多い。(トライアル的な分析のためにデータ数を減らすときなんかはslice()が便利なのだけど。)
そのためfilter()を使って、条件式を用いて絞り込むということがよく行われる。前回記事では、テーブル結合した後に欠損値になっている行を抽出するというところで使った。なお、条件式は複数設定できる。
> filter(x, SEX == "男")
NO SEX AGE ShoCo Kibo
1 1 男 26 1 2
2 2 男 28 3 6
3 4 男 25 5 1
> filter(x, SEX == "男", AGE > 27)
NO SEX AGE ShoCo Kibo
1 2 男 28 3 6
filter()の亜種として、特定列のトップNで絞り込むという条件式が予め組み込まれた、top_n(x, N, 列)という関数がある。
上位で絞り込んだら順位で並んでいてほしいのだけれど、勝手に並べかえてくれるということはないので、オーソドックスなやり方で降順に並べ替えてみたのが下。まあ、joinの前処理の場合はここで並べ替える必要はないわけだけれども。
> top_n(x, 3, AGE)
NO SEX AGE ShoCo Kibo
1 2 男 28 3 6
2 3 女 27 4 3
3 6 女 29 3 1
> top_n(x, 3, AGE) %>% .[order(.$AGE, decreasing = T),]
NO SEX AGE ShoCo Kibo
3 6 女 29 3 1
1 2 男 28 3 6
2 3 女 27 4 3
> top_n(x, 3, AGE) %>% arrange(desc(AGE))
NO SEX AGE ShoCo Kibo
1 6 女 29 3 1
2 2 男 28 3 6
3 3 女 27 4 3
今日はここまで。
この記事が気に入ったらサポートをしてみませんか?