Reports

Twitter: @mtknnktm.

Pixivの北斗の拳のイラストのタグ情報についてアソシエーション分析してみた

はじめに

アソシエーション分析とは、ある項目Aが出現する場合に項目Bも出現するという項目の関連性を表すルール(相関ルール)を抽出して分析するテクニックです。
このAは条件部、Bは結論部と呼ばれます。また元となるデータの1つ1つはトランザクションと呼ばれます。
この記事ではPixivのイラストに付けられたタグ情報についてアソシエーション分析をします。
1つのイラストに付けられたタグのまとまりをトランザクションとし、あるタグがそのトランザクション中に出現した場合、どのようなタグが一緒に出現しやすいかというルールを見ていきます。
ちなみにアソシエーション分析は、小売店の買い物カゴに一緒に入れられて購入された商品の組み合わせを理解することによく使われるため、バスケット分析とも呼ばれています。

というわけでイラストのタグについてアソシエーション分析をすると「どんなタグが同時に付けられているか?」がわかります。
今回は北斗の拳のイラストにおいて、どのキャラクターがどんな組み合わせで描かれているか?調べてみます。

イラスト情報取得(Ruby

まずPixivのイラスト情報を取得します。
APIの叩き方や詳細については以下のページを参考にしました。

# -*- encoding: utf-8 -*-

require 'httpclient'

hc = HTTPClient.new

tag = "北斗の拳" #検索タグ
maxp = 50 #取得したい最大ページ

# PHPSESSIDを入れる。pixivのajaxリクエストのリクエストパラメータを漁ればどこかにある。
# 無効な値を入れても値は取得できるが、その場合は数ページしか取得できない
id = "PHPSESSID" 

for page in 1..maxp do
  csv = hc.get_content("http://spapi.pixiv.net/iphone/search.php?s_mode=s_tag", "p" => page, "word" => tag, "PHPSESSID" => id)
  csv = csv.gsub(/,\n/, "\n") #最後にカンマが付いているので除去
  print csv
  sleep(1) #ちょっと気を使ってみる
end

アソシエーション分析(R)

上記でダウンロードしたイラスト情報のタグについてアソシエーション分析をしてみます。
以下のcharas.txtは、キャラクターのタグについてのみ分析したいので、キャラクターを抜き出すためにキャラクタ名一覧を保存してあるファイルです。
Wikipedia北斗の拳の登場人物一覧から作成しました。

library('arules')

# キャラクタ名の読み込み
charas <- unique(read.table('charas.txt'))
names(charas) <- c('full')

# ダウンロードしたイラスト情報を読み込んでタグ情報のみ抜き出し
pic_data <- read.table('pixiv_hokuto.csv', sep=',')
tags_data <- data.frame(pic_data$V14)
names(tags_data) <- c('base')

tags_data$tags <- apply(tags_data, 1, function(row){
  tags <- c()
  base <- data.frame(strsplit(row['base'], "[ _-]"))
  names(base) <- c('tag')
  # 各イラスト情報について各キャラクタ名が含まれているか1つずつ調べる。
  # あまりいいやり方じゃない(´・ω・`) というか無駄にすっごい重い
  for(n in charas$full){
    if(length(subset(base, tag == n)$tag) > 0){
      tags <- c(tags, n)
    }
  }
  if(length(tags) > 0){
    tags
  }else{
    NULL
  }
})

tran <- as(as.list(tags_data$tags), 'transactions')

# 出現頻度(support)が0.005 (0.5%) 以上の組み合わせを対象とします。
ap <- apriori(tran, parameter = list(support=0.005,confidence=0.01, maxlen=5))

# 結果をソートしてLift順に表示
inspect(head(sort(ap, by = 'lift'), 30))

以下が実行結果です。

1  {リン}       => {バット}      0.0084 0.47727273 25.9387352
2  {バット}     => {リン}        0.0084 0.45652174 25.9387352
3  {サウザー,                                                
    レイ}       => {シン}        0.0060 0.68181818 16.5489850
4  {リュウガ}   => {ジュウザ}    0.0072 0.30508475 13.6198547
5  {ジュウザ}   => {リュウガ}    0.0072 0.32142857 13.6198547
6  {シン,                                                    
    レイ}       => {ユダ}        0.0064 0.59259259 11.4843526
7  {シン,                                                    
    ユダ}       => {レイ}        0.0064 0.69565217 10.7353731
8  {ケンシロウ,                                              
    ジャギ,                                                  
    トキ}       => {ラオウ}      0.0108 0.96428571 10.0866707
9  {シン,                                                    
    レイ}       => {サウザー}    0.0060 0.55555556  8.4688347
10 {ケンシロウ,                                              
    ジャギ,                                                  
    ラオウ}     => {トキ}        0.0108 0.93103448  8.3426029
11 {サウザー,                                                
    シン}       => {レイ}        0.0060 0.53571429  8.2671958
12 {ユダ,                                                    
    レイ}       => {シン}        0.0064 0.34042553  8.2627556
13 {ケンシロウ,                                              
    トキ}       => {ラオウ}      0.0152 0.73076923  7.6440296
14 {ジャギ,                                                  
    トキ,                                                    
    ラオウ}     => {ケンシロウ}  0.0108 0.93103448  7.5817140
15 {ケンシロウ,                                              
    トキ,                                                    
    ラオウ}     => {ジャギ}      0.0108 0.71052632  6.7798313
16 {ケンシロウ,                                              
    ジャギ}     => {ラオウ}      0.0116 0.64444444  6.7410507
17 {ジャギ,                                                  
    ラオウ}     => {トキ}        0.0116 0.72500000  6.4964158
18 {ジャギ,                                                  
    トキ}       => {ラオウ}      0.0116 0.58000000  6.0669456
19 {ジャギ,                                                  
    ラオウ}     => {ケンシロウ}  0.0116 0.72500000  5.9039088
20 {ユダ}       => {レイ}        0.0188 0.36434109  5.6225476
21 {レイ}       => {ユダ}        0.0188 0.29012346  5.6225476
22 {ケンシロウ,                                              
    ラオウ}     => {トキ}        0.0152 0.62295082  5.5819966
23 {ケンシロウ,                                              
    ジャギ}     => {トキ}        0.0112 0.62222222  5.5754679
24 {トキ,                                                    
    ラオウ}     => {ケンシロウ}  0.0152 0.64406780  5.2448518
25 {ケンシロウ,                                              
    トキ}       => {ジャギ}      0.0112 0.53846154  5.1379918
26 {マミヤ}     => {レイ}        0.0084 0.31818182  4.9102132
27 {レイ}       => {マミヤ}      0.0084 0.12962963  4.9102132
28 {トキ,                                                    
    ラオウ}     => {ジャギ}      0.0116 0.49152542  4.6901281
29 {ジャギ,                                                  
    トキ}       => {ケンシロウ}  0.0112 0.56000000  4.5602606
30 {ケンシロウ,                                              
    ラオウ}     => {ジャギ}      0.0116 0.47540984  4.5363534

見方ですが、例えば以下のケンシロウ・ジャギ・ラオウの例だと、

   lhs             rhs          support confidence      lift
6  {ケンシロウ,                                             
    ジャギ}     => {ラオウ}      0.0116  0.6444444  6.741051
  • ケンシロウとジャギがタグ付けされ、かつ、ラオウもタグ付けされる場合は 1.16% (support)
  • ケンシロウとジャギがタグ付けされた場合の内、ラオウも同時にタグ付けされている割合は 64.44% (confidence)
  • リフト値(lift)は「ラオウがタグ付けされている場合」に対して「ケンシロウとジャギがタグ付けされ、かつ、ラオウもタグ付けされる場合」はどの程度よく現れるか?を表します(ほとんどのイラストにラオウがタグ付けされていればこの値は小さく、ケンシロウとジャギがタグ付けされているイラストのみにラオウがタグ付けされていればこの値は大きくなります)


それで、上記の結果をみてみるとリフト値が高い組み合わせのトップはリンとバットでした。
出現頻度(support)はそんなに高くないので、タグ付け頻度はそんなに高くないけど、出てくるときは大抵セットということです。
次いで、サウザー・レイ・シン、リュウガ・ジュウザになっています。
シンって本編でこの2人と絡んでましたっけ…情報求ム!
その次がシン・レイ・ユダ様と他の南斗とほとんど絡みのないシンに妙に人気が集まっています
次いで北斗四兄弟です。
北斗四兄弟の組み合わせは出現頻度は全体的に高めですが、それぞれ独立にタグ付けされることも多いのでリフト値はなかなか大きくならないようです。

全体的に割りと順当な気がしますが、シンがあまり絡みの無かった南斗系にいろんな組み合わせで出てくるのが以外でした。
あと、アミバ・トキはもっと上位に来ると思ってたんですがそうでも無かったです(表示件数を増やしてやると出てきます)。

まとめ

というわけで、Pixivの北斗の拳のイラストのタグ情報についてアソシエーション分析をしてみました。
その結果、どんな組み合わせのキャラクターがどんなふうにタグ付されているかを定量的に見ることが出来ました。
色々試してみたら意外な組み合わせが発見できるかもしれません。