この記事は、R Advent Calendar 2015 15日目の記事です。
タワレコの洋楽コーナーに行くと
「Pitchforkで○○点獲得!」
のようなポップが付けられているのをちらほら見かけます。
これは、Pitchforkという音楽メディアが10点満点でアルバムを評価する点数です。インディー系の音楽レビューに定評があり、日本であまり知られていないアーティストのアルバムを売り出す時は、箔を付けるためにこの点数を持ち出したりします。
新譜で10点満点を取るアルバムは1年に1枚あるかないかです。ということで、10点満点取るのがすごいのは分かります。
でも、「Pitchforkで8.3点獲得!」とか言われた時に、それがどれくらいすごいのかピンときません。ということで、点数の分布とかを調べてみたいと思います。
Pitchforkのデータをスクレイピング
Pitchforkは偉大なメディアだと個人的には思っているのでデータだけぶっこ抜いてくるのはとても心苦しいのですが、男には心を鬼にしてやらねばならぬときがあります。そう、アドベントカレンダーです。それは今です。
ということで、2015年のデータを決断的にスクレイピングします。
Pitchforkのレビューページの構成
これより、便宜上、↓のようなレビューされたアルバムが一覧で並んでいるページを「レビュー一覧ページ」、
↓のような、「レビュー一覧ページ」でアルバムをクリックすると飛ぶ各レビューの詳細ページを「レビュー詳細ページ」と呼ぶことにします。
レビュー点数はPitchforkの売りのひとつなので、レビュー一覧ページでは点数が分からないようになっています。クリックしてレビュー詳細ページに行くまで点数がわかりません。
レビュー詳細ページのURLをスクレイピングする
レビュー一覧ページのURLは、1ページ目がhttp://pitchfork.com/reviews/albums/1/
、2ページ目がhttp://pitchfork.com/reviews/albums/2/
...というような法則性になっています。60ページくらい遡ると2014年のレビューになったので、そのあたりまでを取ってくればよさそうです。
解説の詳細は省きますが、rvestパッケージをつかってスクレイピングします。read_html()
するところは、連続でやるとうまく取れなかったのでスリープを入れます。
※purrrパッケージについては@sinhrksさん(a.k.a. うさぎさん)のJapan.Rでの発表なんかを参考にしてみてください。
library(rvest) library(purrr) pages <- map(1:60, ~ sprintf("http://pitchfork.com/reviews/albums/%d/", .)) %>% map(~ { Sys.sleep(3); read_html(.) }) %>% map(~ html_nodes(., "ul.object-grid a")) %>% map(~ html_attr(., "href")) combine(pages) %>% sprintf("http://pitchfork.com%s", .) %>% cat(., file = "./pitchfork.list", sep = "\n")
レビュー詳細ページをスクレイピングする
さて、上のスクレイピングで集まったURLは1200あります。ここでスクレイピングガチ勢であれば様々な技を駆使しつつ自力でスクレイピングするのでしょう。
が、ゆるふわスクレイパーな私はそんなことはできないので、私の代わりにスクレイピングしてくれるウェブサービス・import.ioの力に頼ります。
(R Advent Calendarの記事なのにRじゃないのを使ってすみません。。)
import.ioにはいくつか機能がありますが、今回使うのはExtractorです。
詳細は省きますが、ざっくり流れだけ。
まず、Extractorを設定します。ページのどの部分を取ってくるかをマウスでクリックして選んでいけばそれっぽいのができます。
次にBulk Extractを使って、先ほど取ってきた1200個のURLをスクレイピングします。
Bulk Extract Tutorial – import.io Knowledge Base
失敗したものがあれば、「X URLx failed」と書いてあるリンクが表示されるので、それをクリックします。するとポップアップが出てくるのでその「Retry failures」をクリックすればやり直してくれます。
右上の「Export」から「Spreadsheet」を選ぶとCSVで出力できます。
データ前処理
まずはデータを読み込みます。
library(readr) library(dplyr) reviews <- read_csv("pitchfork_reviews.csv") glimpse(reviews) #> Observations: 1,200 #> Variables: 12 #> $ artist (chr) "http://pitchfork.com/artists/33377-archy-marshall/", "http://pitchfork.com/artists/33373-wiki/", "http://pit... #> $ rating (chr) "8.6", "7.6", "8.5; 8.5; 9; 7.6; 8.8; 7", "7.2", "7.3", "8.5", "7", "7.5", "5", "6.7", "8.3", "6.4", "6.7", "... #> $ label (chr) "XL / True Panther; 2015", "Letter Racer; 2015", "Grönland; 2015; Grönland; 1974/2015; Grönland; 1975/2015; G... #> $ reviewer (chr) "http://pitchfork.com/staff/jayson-greene/", "http://pitchfork.com/staff/paul-a-thompson/", "http://pitchfork... #> $ title (chr) "A New Place 2 Drown", "Lil Me", "Complete Works; Musik Von Harmonia; Deluxe; Tracks and Traces; Live 1974; D... #> $ rating/_source (chr) "8.6", "7.6", "8.5; 8.5; 9.0; 7.6; 8.8; 7.0", "7.2", "7.3", "8.5", "7.0", "7.5", "5.0", "6.7", "8.3", "6.4", ... #> $ reviewer/_text (chr) "Jayson Greene", "Paul A. Thompson", "Mark Richardson; Mark Richardson; Mark Richardson; Mark Richardson; Mar... #> $ review_date (chr) "December 11, 2015", "December 11, 2015", "December 11, 2015; December 11, 2015; December 11, 2015; December ... #> $ artist/_source (chr) "/artists/33377-archy-marshall/", "/artists/33373-wiki/", "/artists/8797-harmonia/; /artists/8797-harmonia/; ... #> $ artist/_text (chr) "Archy Marshall", "Wiki", "Harmonia; Harmonia; Harmonia; Harmonia & Eno '76; Harmonia; Harmonia", "The Spook ... #> $ reviewer/_source (chr) "/staff/jayson-greene/", "/staff/paul-a-thompson/", "/staff/mark-richardson/; /staff/mark-richardson/; /staff... #> $ pageUrl (chr) "http://pitchfork.com/reviews/albums/21326-a-new-place-2-drown/", "http://pitchfork.com/reviews/albums/21329-...
ちょっと設定が適当だったので、不要なデータを取り除いたり日付や数値をパースしたりします。
レビュー紹介ページ?を取り除く
rating
を数値に変換するときに、うまくパースできない奴があるのに気付きました。調べると、rating
がこんな風になっています。
$ rating (chr) "8.5; 8.5; 9; 7.6; 8.8; 7"
これは、複数のアルバムの紹介をしているページです。
でも、それぞれのレビューは別のページにあるので、このレビューは除外してよさそうです。rating
に;
が入っていたら除外するようにします。
library(stringr) reviews_no_summary <- reviews %>% filter(!str_detect(rating, ";"))
変換
library(lubridate) # 必要なカラムだけを選択、数値や日付はパースする reviews_parsed <- reviews_no_summary %>% transmute(artist = `artist/_text`, title, rating = as.numeric(rating), review_date = parse_date_time(review_date, orders = "BdY", locale = "C"), reviewer = `reviewer/_text`, label) # labelは「レーベル名; 発売年」となっているので、別々のカラムに分ける reviews_tidy <- reviews_parsed %>% separate(label, into = c("label", "published"), sep = "; ") knitr::kable(slice(reviews_tidy, 1:10))
artist | title | rating | review_date | reviewer | label | year |
---|---|---|---|---|---|---|
Archy Marshall | A New Place 2 Drown | 8.6 | 2015-12-11 | Jayson Greene | XL / True Panther | 2015 |
Wiki | Lil Me | 7.6 | 2015-12-11 | Paul A. Thompson | Letter Racer | 2015 |
The Spook School | Try to Be Hopeful | 7.2 | 2015-12-11 | Quinn Moreland | Fortuna Pop! | 2015 |
Various Artists | Christians Catch Hell: Gospel Roots 1976-79 | 7.3 | 2015-12-11 | J. Edward Keyes | Honest Jon's | 2015 |
Baroness | Purple | 8.5 | 2015-12-10 | Brandon Stosuy | Abraxan Hymns | 2015 |
Rick Ross | Black Market | 7.0 | 2015-12-10 | Julian Kimble | Maybach/Warner Bros. | 2015 |
よさそうです。これをいろいろ調べてみます。
レビュー登場回数が多いアーティスト
dplyrパッケージのcount()
でさくっと調べます。
reviews_tidy %>% count(artist, sort = TRUE) %>% slice(1:10) %>% knitr::kable(.)
artist | n |
---|---|
Various Artists | 23 |
Chief Keef | 4 |
Future | 3 |
Young Thug | 3 |
Alessia Cara | 2 |
Andre Bratten | 2 |
Andrew Hung | 2 |
Aphex Twin | 2 |
Beach House | 2 |
Bitchin Bajas | 2 |
Various Artistsがを除くと一位はChief Keef。
...誰?
うーん、ヒップホップ系は詳しくなくてわからないです。。
というか、この中で知ってるのはAphex Twinくらいしかないです。不勉強を恥じるばかりです。
点数が高いアルバム
点数が高いアルバム上位10個を見てみます。
reviews_tidy %>% arrange(desc(rating)) %>% slice(1:10) %>% knitr::kable(.)
artist | title | rating | review_date | reviewer | label | year |
---|---|---|---|---|---|---|
John Coltrane | A Love Supreme: The Complete Masters | 10.0 | 2015-11-25 | Mark Richardson | Verve | 2015 |
A Tribe Called Quest | People's Instinctive Travels and the Paths of Rhythm | 10.0 | 2015-11-13 | kris ex | Legacy | 1990/2015 |
The Velvet Underground | Loaded: Re-Loaded 45th Anniversary Edition | 10.0 | 2015-11-04 | Stuart Berman | Atlantic | 1970/2015 |
The Rolling Stones | Sticky Fingers | 10.0 | 2015-06-19 | Mark Richardson | Rolling Stones | 1971/2015 |
Built to Spill | There’s Nothing Wrong With Love | 9.3 | 2015-10-23 | Mark Richardson | Sub Pop / Up | 1994/2015 |
Tame Impala | Currents | 9.3 | 2015-07-13 | Ian Cohen | Interscope | 2015 |
Jamie xx | In Colour | 9.3 | 2015-06-01 | Mark Richardson | Young Turks | 2015 |
Sufjan Stevens | Carrie & Lowell | 9.3 | 2015-03-30 | Brandon Stosuy | Asthmatic Kitty | 2015 |
Kendrick Lamar | To Pimp a Butterfly | 9.3 | 2015-03-19 | Craig Jenkins | Interscope / Aftermath / Top Dawg | 2015 |
The Flaming Lips | Heady Nuggs: 20 Years After Clouds Taste Metallic | 9.1 | 2015-11-24 | Stuart Berman | Warner Bros. | 1995/2015 |
えっ、10点が4つもある?? 2015年は歴史上稀に見る豊作の年だったのか!!!
とか思っちゃうかもしれませんが、落ち着きましょう。落ち着け俺。
ここで、yearに2つの年が出てきているものが多いことに気付きます。これはつまり、リイシュー(再版盤)です。あと、1番上のも「A Love Supreme: The Complete Masters」と書いてあるように、ベスト盤的なやつです。上に
新譜で10点満点を取るアルバムは1年に1枚あるかないかです。
と書きましたが、新譜じゃなかったらけっこうあるみたいです。タイトルからベスト盤かを推測するのは難しいですが、とりあえずリイシュー盤とそうじゃないやつで、点数の分布を比べてみましょう。
library(ggplot2) reviews_tidy %>% mutate(is_reissued = str_detect(year, "/")) %>% { ggplot(., aes(is_reissued, rating)) + geom_violin(scale = "count") }
やはりリイシューされた方が点数が高めになってそうです。
とりあえずyear
でわかるやつだけでいいので、リイシュー盤は除外して考えることにします。
reviews_fresh <- reviews_tidy %>% filter(year == "2015")
レビュワーごとの偏り
ひょっとして、レビュワーによってつける点数がめちゃくちゃ違ったりするのではないでしょうか。調べてみます。
gridExtra::grid.arrange( ggplot(reviews_fresh, aes(rating, group = reviewer)) + geom_density(), # review数が20以上のレビュワーのみ ggplot(filter(group_by(reviews_fresh, reviewer), n() > 20), aes(rating, group = reviewer)) + geom_density() )
1点弱の違いはありそうな雰囲気ですが、まあそんなものなのかも。
全体の点数分布
点数の分布は以下のようになっています。
qu <- quantile(reviews_fresh$rating, probs = c(0.5, 0.75, 0.9, 0.95)) qu #> 50% 75% 90% 95% #> 7.2 7.6 8.0 8.3 ggplot(reviews_fresh, aes(rating)) + geom_density() + geom_vline(xintercept = qu, colour = "red")
たとえば8.3点以上なら、上位5%に入っているということになります。
最後に
Advent Calendarのときくらいちゃんとデータ分析の記事を書こうと思ったんですが、実は、担当日が明日だと思い込んでいて時間がなくなりました...。
2日前じゃなくてあと1時間半だという壮大な勘違いに偶然気付いてしまった俺たちは。
— Hiroaki Yutani (@yutannihilation) December 14, 2015
ということで最後は、今年9.3を獲得してで最上位タイだった4曲を紹介してお茶を濁します。すみません。。
Tame Impala - Currents
オーストラリアはパース出身の5人組。MGMT系統の、モダンなサイケロックといったところ。個人的には、いつの間にこんなブレイクしたの??という感じ。
Jamie xx - In Colour
言わずと知れたThe xxのブレーンのソロアルバム。Gil Scott-Heronのリミックスもソロワークではあったけど、完全オリジナルとしては一作目。相変わらず、聴けば「ああxxだな」とわかるこの音。個人的には、こういうのもいいけど、The xxの1作目みたいなミニマルな音作りのをまた出してほしい。
Sufjan Stevens - Carrie & Lowell
フォーク。いい感じのサイズの音。
Kendrick Lamar - To Pimp a Butterfly
ラップよく分からない。エモそう。よく分からないけど(適当)
感想
個人的に今年のクリーンヒットはDarkstarだったんですが、Pitchforkではレビューすらされていませんでした。そもそも私の音楽的嗜好ではPitchforkの点数は役に立たないのかも、と思いました...。