読者です 読者をやめる 読者になる 読者になる

いずにゃんの研究日記

専門性を広げるための練習場

RでAnime APIから季節のアニメ情報を読み込んで一覧できるデータフレームにする

3か月ごとに,アニメの新番組チェックが忙しくなる時期がやってくる。 こんなとき,放映されるアニメ番組一覧の情報を手軽に作成できたら便利である。 それがRでできたらさらに心健やかになるに違いない。

アニメ番組一覧の情報について,アニメとITの融合「Anitech」を 促進している秋葉原IT戦略研究所さまがとても素晴らしい 仕組みを提供している。

qiita.com

これにアクセスすれば,JSON形式で様々なアニメ番組情報が取得できる。 以下,Rでどうやって行うかを解説する。なお,R Studioを使用している。


RからAnime APIを呼び出す

library(RCurl)

getURL()関数で読み込む先のURLを指定する。 ここでは,2017年の冬アニメを指定しているので,URLの末尾が/2017/1となっている。ここの西暦(2014年以降)と最後の番号(1~4)を変えれば,他の季節のアニメ情報も取得できる。

getdata.json <- getURL('http://api.moemoe.tokyo/anime/v1/master/2017/1')

これでJSON形式の情報はRに読み込めた。しかし,Rでこれを閲覧するためには,まずJSON形式からlist形式に変換する必要がある。そこで登場するのが次のパッケージである。

library(rjson)

変換は次のコードの通りである。

getdata.list <- fromJSON(getdata.json)

少し出力が長くなってしまうがstr()を使うとどういうデータが 読み込まれているのか,listの構造を把握できる。

str(getdata.list)

最初の1作品の結果を示すと,

List of 40
 $ :List of 15
  ..$ title_short2    : chr ""
  ..$ twitter_account : chr "anime_aimaimi"
  ..$ public_url      : chr "http://www.dreamcreation.co.jp/aimaimi3/"
  ..$ title_short1    : chr "あいまいみ"
  ..$ sex             : num 0
  ..$ twitter_hash_tag: chr "あいまいみー"
  ..$ id              : num 475
  ..$ sequel          : num 3
  ..$ created_at      : chr "2017-01-03 01:10:03.0"
  ..$ city_name       : chr ""
  ..$ cours_id        : num 13
  ..$ title           : chr "ちょぼらうにょぽみ劇場第三幕 あいまいみー~Surgical Friends~"
  ..$ city_code       : num 0
  ..$ title_short3    : chr ""
  ..$ updated_at      : chr "2017-01-03 01:10:03.0"

のようになる。しかしこれでは少し中身が把握しづらい。 こんなときに便利なのが,listviewerパッケージである。

qiita.com

library(listviewer)
jsonedit(getdata.list)

と実行すると,以下のようにRstudio内で見やすい形式に中身を 確認して,listの構造も確認できる。

f:id:izunyan:20170108200619j:plain


listから必要なデータを抜き出して,データフレームにする

1つのアニメ作品に様々な情報が付与されているので,分かりやすくするためとりあえず,3つの変数(作品名,webサイトURL,twitterアカウント) として情報を抜き出してみる。これにはlapplyを使う。

Title <- as.character(lapply(getdata.list, '[[','title'))
Web <- as.character(lapply(getdata.list, '[[','public_url'))
Twitter <- as.character(lapply(getdata.list, '[[','twitter_account'))

ここの'[['というのが最初よく理解できないと思うが,詳しい説明は

複数の行列、データフレームからなるリストの各成分から特定要素を抽出する (from r-help, 2004.09.17)

などを参照すると分かるかもしれない。あとは,この3つの変数(ベクトル)をデータフレームにまとめるだけである。データ表示に便利なtibble形式にする。

library(dplyr)
dat <- data_frame(title=Title,web=Web,twitter=Twitter)
dat

f:id:izunyan:20170108200711j:plain

環境によっては長くなっている部分の変数名は省略されて表示されているかもしれないが,これで今季のアニメ視聴に役立つリストがデータフレームとして作成できた。あとはcsvで出力するなど好きなように使えばよい。


追記(2017/02/12)

申し遅れてしまったが,本記事のコードは以下の解説を大いに参考にさせていただいている。RESAS-APIについてもその内まとめてみたい。

qiita.com

はじめてのtidyr(1):データをwideからlongにする,その逆も

サンプルデータは下記記事を参照。

izunyan.hatenablog.com

        name grade height  B  W  H
1   高海千歌     2    157 82 59 83
2   桜内梨子     2    160 80 58 82
3   松浦果南     3    162 83 58 84
4 黒澤ダイヤ     3    162 80 57 80
5     渡辺曜     2    157 82 57 81
6   津島善子     1    156 79 58 80
7 国木田花丸     1    152 83 57 83
8   小原鞠莉     3    163 87 60 84
9 黒澤ルビィ     1    154 76 56 79

このように,1行に1人のデータが入っているのがよく見るデータの形であるが,解析によっては1人のデータを数行にわたらせるときがある。たとえば,複数の測定時点の変数がt1, t2, t3…と変数としてあり,それをtimeという1つの変数にまとめて縦に値を表示させたいといった場合などである。

ここではあまりあてはまらないかもしれないが,強引に身長とスリーサイズを1つの変数で表したいとする。

つまり,横長(wide)データを縦長(long)データに変換する。そんなときに便利なのがtidyrパッケージである。チートシートでは,"Reshaping Data"の部分に出てくる。

tidyrが入っていない人は,ネットにつながった環境で以下を実行

install.packages("tidyr")

まずはtidyrを読み込む。なお,%>%演算子を使うので,dplyrも読み込む。

library(tidyr)
library(dplyr)


wideからlongへの変換

wideからlongへの変換はgather( )で行う。 新しい変数bodyにheight, B, W, Hという変数名が値として入り,同じく新しい変数valueに先ほどの変数名の対応するデータが入るという構造である。nameとgradeには-をつけたが,これは変換せずそのまま残す際の記号である。

dat_long <- dat %>% gather(body,value,-name,-grade)
dat_long

次のようなデータ構造に変換された。

         name grade   body value
1    高海千歌     2 height   157
2    桜内梨子     2 height   160
3    松浦果南     3 height   162
4  黒澤ダイヤ     3 height   162
5      渡辺曜     2 height   157
6    津島善子     1 height   156
7  国木田花丸     1 height   152
8    小原鞠莉     3 height   163
9  黒澤ルビィ     1 height   154
10   高海千歌     2      B    82
11   桜内梨子     2      B    80
12   松浦果南     3      B    83
13 黒澤ダイヤ     3      B    80
14     渡辺曜     2      B    82
15   津島善子     1      B    79
16 国木田花丸     1      B    83
17   小原鞠莉     3      B    87
18 黒澤ルビィ     1      B    76
19   高海千歌     2      W    59
20   桜内梨子     2      W    58
21   松浦果南     3      W    58
22 黒澤ダイヤ     3      W    57
23     渡辺曜     2      W    57
24   津島善子     1      W    58
25 国木田花丸     1      W    57
26   小原鞠莉     3      W    60
27 黒澤ルビィ     1      W    56
28   高海千歌     2      H    83
29   桜内梨子     2      H    82
30   松浦果南     3      H    84
31 黒澤ダイヤ     3      H    80
32     渡辺曜     2      H    81
33   津島善子     1      H    80
34 国木田花丸     1      H    83
35   小原鞠莉     3      H    84
36 黒澤ルビィ     1      H    79

分かりにくいので,名前でソートしてみる。

dat_long %>% arrange(name)
         name grade   body value
1    高海千歌     2 height   157
2    高海千歌     2      B    82
3    高海千歌     2      W    59
4    高海千歌     2      H    83
5  国木田花丸     1 height   152
6  国木田花丸     1      B    83
7  国木田花丸     1      W    57
8  国木田花丸     1      H    83
9  黒澤ダイヤ     3 height   162
10 黒澤ダイヤ     3      B    80
11 黒澤ダイヤ     3      W    57
12 黒澤ダイヤ     3      H    80
13 黒澤ルビィ     1 height   154
14 黒澤ルビィ     1      B    76
15 黒澤ルビィ     1      W    56
16 黒澤ルビィ     1      H    79
17   桜内梨子     2 height   160
18   桜内梨子     2      B    80
19   桜内梨子     2      W    58
20   桜内梨子     2      H    82
21   小原鞠莉     3 height   163
22   小原鞠莉     3      B    87
23   小原鞠莉     3      W    60
24   小原鞠莉     3      H    84
25   松浦果南     3 height   162
26   松浦果南     3      B    83
27   松浦果南     3      W    58
28   松浦果南     3      H    84
29   津島善子     1 height   156
30   津島善子     1      B    79
31   津島善子     1      W    58
32   津島善子     1      H    80
33     渡辺曜     2 height   157
34     渡辺曜     2      B    82
35     渡辺曜     2      W    57
36     渡辺曜     2      H    81

このように,1名につき4行のlongなデータ構造に変換された。 つまり,9名×4で36行のデータとなった。


longからwideへの変換

これを逆にlongからwideに変換したいときはspread( )を使う。横長に並べなおす部分の変数だけ( )内に並べる

dat_long %>% spread(body,value) 

これでlongからwideに変換された。つまり元に戻った。

        name grade height  B  W  H
1   高海千歌     2    157 82 59 83
2   桜内梨子     2    160 80 58 82
3   松浦果南     3    162 83 58 84
4 黒澤ダイヤ     3    162 80 57 80
5     渡辺曜     2    157 82 57 81
6   津島善子     1    156 79 58 80
7 国木田花丸     1    152 83 57 83
8   小原鞠莉     3    163 87 60 84
9 黒澤ルビィ     1    154 76 56 79

はじめてのdplyr(3):適切なデータ表示になるデータフレームの便利版

チートシートのいちばん最初,"Syntax"の部分で紹介されている,大規模データを扱う時に重宝するデータセットの作成方法について説明する。

次のような行数の多いデータセットを作成してみる。以下のコードをコピペして実行すればデータができる。

dat <- data.frame(maru=rep("ずら",100),ruby=rep("ピギィ",100), yoshiko=rep("ギラン",100),you=rep("ヨーソロー",100))

#データとして使用されている言葉の意味はアニメ「ラブライブ!サンシャイン!!」を視聴すると分かる

これは100行にもわたるので,datと打ってデータセット全部を表示させるのに躊躇するだろう。なので,

head(dat)
  maru   ruby yoshiko        you
1 ずら ピギィ  ギラン ヨーソロー
2 ずら ピギィ  ギラン ヨーソロー
3 ずら ピギィ  ギラン ヨーソロー
4 ずら ピギィ  ギラン ヨーソロー
5 ずら ピギィ  ギラン ヨーソロー
6 ずら ピギィ  ギラン ヨーソロー

として最初の数行を表示させるのが普通と思う。

dplyrではtbl_df( )を使ってもっとデータ表示に便利なデータフレームに変換できる。

library(dplyr)

dat <- tbl_df(dat)
dat
# A tibble: 100 × 4
    maru   ruby yoshiko
   <chr>  <chr>   <chr>
1   ずら ピギィ  ギラン
2   ずら ピギィ  ギラン
3   ずら ピギィ  ギラン
4   ずら ピギィ  ギラン
5   ずら ピギィ  ギラン
6   ずら ピギィ  ギラン
7   ずら ピギィ  ギラン
8   ずら ピギィ  ギラン
9   ずら ピギィ  ギラン
10  ずら ピギィ  ギラン
# ... with 90 more rows, and
#   1 more variables:
#   you <chr>

このように,画面の大きさを考慮して変数youは省略され,行数も10行のみで残り90行あるよ,との表示が出る。

正確にはtibbleパッケージだが,dplyrを呼び出してあれば,データフレームを作成する所からこのタイプのものにできる。このさい,dataframeをつなぐ部分が.ではなく_である所がポイントである。チートシートでは,"Reshaping Data"の部分に出てくる。(20170114追記)

dat2 <- data_frame(maru=rep("ずら",100), ruby=rep("ピギィ",100), yoshiko=rep("ギラン",100), you=rep("ヨーソロー",100))

dat2もtbl_df( )で変換されたdatと同様のデータ表示となる。

はじめてのdplyr(2):平均値を算出しデータセットに追加,層別の計算も

前回の

izunyan.hatenablog.com

の続きを解説する。サンプルデータは上記記事を参照。

まずは,単純に身長の平均値をheightmという名前で作成してみる。 チートシートでは,"Summarise Data"の部分。

dat %>% summarise(heightm=mean(height))
   heightm
1 158.1111


算出した平均値を変数としてデータセットに追加する

算出した値を新たに変数として付け加えたい場合は,mutate( )を使う。 チートシートでは,"Make New Variables"の部分。

dat %>% mutate(heightm=mean(height))
        name grade height  B  W  H  heightm
1   高海千歌     2    157 82 59 83 158.1111
2   桜内梨子     2    160 80 58 82 158.1111
3   松浦果南     3    162 83 58 84 158.1111
4 黒澤ダイヤ     3    162 80 57 80 158.1111
5     渡辺曜     2    157 82 57 81 158.1111
6   津島善子     1    156 79 58 80 158.1111
7 国木田花丸     1    152 83 57 83 158.1111
8   小原鞠莉     3    163 87 60 84 158.1111
9 黒澤ルビィ     1    154 76 56 79 158.1111


層別・グループ別に計算

group_by( )を使うと,層・グループ別に処理が行える。そして,ここで %>%演算子の真価が発揮される。学年ごとに身長を出してみる場合は次のようになる。チートシートでは,"Group Data"の部分。

dat %>% group_by(grade) %>% summarise(heightm=mean(height))
# A tibble: 3 × 2
  grade  heightm
  <dbl>    <dbl>
1     1 154.0000
2     2 158.0000
3     3 162.3333

これらの平均値をデータセットに変数として追加したい場合は 次のようにする。

dat %>% group_by(grade) %>% mutate(heightm=mean(height))
        name grade height     B     W     H  heightm
      <fctr> <dbl>  <dbl> <dbl> <dbl> <dbl>    <dbl>
1   高海千歌     2    157    82    59    83 158.0000
2   桜内梨子     2    160    80    58    82 158.0000
3   松浦果南     3    162    83    58    84 162.3333
4 黒澤ダイヤ     3    162    80    57    80 162.3333
5     渡辺曜     2    157    82    57    81 158.0000
6   津島善子     1    156    79    58    80 154.0000
7 国木田花丸     1    152    83    57    83 154.0000
8   小原鞠莉     3    163    87    60    84 162.3333
9 黒澤ルビィ     1    154    76    56    79 154.0000


層別・グループ別にすべての変数の平均値を算出

このように,%>%は複数の関数をつなげて実行してくれる。1行に並べて書くと長くなるので,%>%の後で改行して複数行に渡り書くこともできる。今まで解説してきた内容に加え,新しくすべての変数に対する処理を行うsummarise_each( )を使い,学年ごとに身長とスリーサイズの平均値を一気に算出するコードを書いてみる。

dat %>% group_by(grade) %>%
        select(-name, -grade) %>%
        summarise_each(funs(mean))
# A tibble: 3 × 5
  grade   height        B        W        H
  <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
1     1 154.0000 79.33333 57.00000 80.66667
2     2 158.0000 81.33333 58.00000 82.00000
3     3 162.3333 83.33333 58.33333 82.66667

名前と学年は平均値を出しても意味がないので,select( )で省いている



変更履歴

2016/12/26 誤字修正

はじめてのdplyr(1):行のソートと選択,変数のkeepとdropまで

本記事は,Rのパッケージdplyrを自分が数日前に使い始めて感動したので,まだ使ってない人が気軽に使えるようになるための解説である。dplyrが使いこなせれば,データの整理が非常に楽になりそう。

すでにdplyrが話題になって久しいことは感じていたが,なかなか踏み出せずにいた。そんな中, kazutan v3.3.2 (@kazutan) | Twitterさんの記事 qiita.com

で紹介されていた,

"Data Wrangling with dplyr and tidyr"  
「dplyrとtidyrによるデータハンドリングのチートシート」

を見て使い始めてみたら,これは使わないと損だと強く感じたので,自分の知識の定着のためにもこの記事を書いてみた。

すでにdplyrの解説はweb上で大量に見つけられるが,本記事の独自性は以下の点にある。


はじめる前に

いくつか準備しておくべき点や実行環境などを示す。

  • 使用したOSはWindows 7
  • RStudioで実行(version 1.0.44)
  • パッケージdplyrをインストール(本記事執筆時点ではversion 0.5.0)

dplyrが入っていない人は,ネットにつながった環境で以下を実行

install.packages("dplyr")


データを読み込む

データは(自分にとって)なじみやすいものがよいので,2016年を代表するアニメ作品の1つである「ラブライブ!サンシャイン!!」から,スクールアイドルグループAqoursのメンバーのデータを使用する。出典はラブライブ!サンシャイン!! Official Web Site

以下のコードを貼り付けて実行したら,データが読みこまれる。

dat <-
  data.frame(
             name=c("高海千歌","桜内梨子","松浦果南","黒澤ダイヤ","渡辺曜","津島善子","国木田花丸","小原鞠莉","黒澤ルビィ"),
             grade=c(2,2,3,3,2,1,1,3,1),
             height=c(157,160,162,162,157,156,152,163,154),
             B=c(82,80,83,80,82,79,83,87,76),
             W=c(59,58,58,57,57,58,57,60,56),
             H=c(83,82,84,80,81,80,83,84,79)
            )
dat
        name grade height  B  W  H
1   高海千歌     2    157 82 59 83
2   桜内梨子     2    160 80 58 82
3   松浦果南     3    162 83 58 84
4 黒澤ダイヤ     3    162 80 57 80
5     渡辺曜     2    157 82 57 81
6   津島善子     1    156 79 58 80
7 国木田花丸     1    152 83 57 83
8   小原鞠莉     3    163 87 60 84
9 黒澤ルビィ     1    154 76 56 79

変数名のgradeは学年,heightは身長(cm),B・W・Hはスリーサイズである。 さて,それではここから実際にdplyrを使ってみよう。

library(dplyr)


行の並び替え(ソート)

入力したデータは並び方が公式サイト掲載順だったので,まずは変数gradeを使って学年順に並び変えてみる。つまりデータのソートである。チートシートでは,"Reshaping Data"の部分に出てくる。

arrange(dat, grade)
        name grade height  B  W  H
1   津島善子     1    156 79 58 80
2 国木田花丸     1    152 83 57 83
3 黒澤ルビィ     1    154 76 56 79
4   高海千歌     2    157 82 59 83
5   桜内梨子     2    160 80 58 82
6     渡辺曜     2    157 82 57 81
7   松浦果南     3    162 83 58 84
8 黒澤ダイヤ     3    162 80 57 80
9   小原鞠莉     3    163 87 60 84

dplyrの解説でよく目にする書き方は,

dat %>% arrange(grade)

であろう。これも同じことができるし便利なのでこの先はこちらに統一するが,解説は以下の通り。

  • %>%という記号を初めて見た方は何これ?と思うかもしれない。これは,パイプ演算子と呼ばれ,%>%の左側にあるものを右側に渡すことを意味している。
    記号で書くと,x %>% f(y) f(x, y) と同じということになる
  • つまり,いちいちデータセット名のdatを書かなくてもよいことになるから,コードが簡単で見やすくなる。他にも利点はあるけど,解説はまたの機会に
  • RStudioならば,Ctrl+Shift+Mで %>% が出てきて便利。(MacはCmd+Shift+Mらしい)
  • チートシートを見ると,すべてにdplyr::とついているが,library()require()dplyrを呼び出してあれば,これは不要


なお降順にソートするにはキーとなる変数をdesc()で囲む。

dat %>% arrange(desc(grade))


行の選択

たとえば今は9名のデータ(行,ケース,またはオブザベーションとも)が表示されているが,1年生だけ表示したい!という時に使用。チートシートでは,"Subset Observations (Rows)"の部分。

dat %>% filter(grade==1)
        name grade height  B  W  H
1   津島善子     1    156 79 58 80
2 国木田花丸     1    152 83 57 83
3 黒澤ルビィ     1    154 76 56 79

filter( )の中身を変えれば好きなように選択できる。 たとえば,

height>=160  (身長160cm以上)
grade!=2  (2年生以外)
grade==1 & B>80    (1年生かつバスト80より上)
height<155 | height>162 (身長155未満,または身長162より上)

これまでは表示するだけだったが,ケースを選択してそれを新しいデータセットにしたい場合がある。その時は次のようにする

dat_grade3 <- dat %>% filter(grade==3)

3年生だけの新しいデータセットdat_grade3ができているはずである。


変数の選択

変数が多すぎると使いたい変数を探すのも大変だったりするので,使いたい変数を選び出したい時がある。 チートシートでは,"Subset Variables (Columns)"の部分。

名前と学年の変数だけを残す。つまり変数のkeep。

dat %>% select(name, grade)
        name grade
1   高海千歌     2
2   桜内梨子     2
3   松浦果南     3
4 黒澤ダイヤ     3
5     渡辺曜     2
6   津島善子     1
7 国木田花丸     1
8   小原鞠莉     3
9 黒澤ルビィ     1

一方,特定の変数を残さないようにしたい場合もある。いわゆる変数のdrop。 そんな時は変数の前に-をつける。

dat %>% select(-name, -grade)
  height  B  W  H
1    157 82 59 83
2    160 80 58 82
3    162 83 58 84
4    162 80 57 80
5    157 82 57 81
6    156 79 58 80
7    152 83 57 83
8    163 87 60 84
9    154 76 56 79

ちなみに,並びが連続している変数については,:で範囲を示すことができる。上の例は,次のコードでも同じ結果になる。

dat %>% select(-name:-grade)