Kitsune Gadget

気になったことをつらつらと

hashtag: 2017IQテスト ってどのくらいの人がどのくらいのスコア出してるか気になった

(2017/12/10 の再掲です)

10月末にツイッターのトレンドになってた気がする。

結果はこんな風にツイートできる。(ユーザーで改変されてなければ) f:id:kitsune-gadget:20180421063255p:plain  

データの取得は10月末にしていた。

とりあえずツイートを取得しよう

pythonを使ってTwitter Search APIから取得し、取得したjsonをそのまま保存してから使う。 キーワードは ハッシュタグ"%23" + "2017IQテスト" で検索し、最新1000件(10月27日当時)を取得した。

API叩いてのツイート取得の説明は他の記事にもありそうだから割愛。

jsonからテキストを抽出して結果数値のみ抜き出す

数値は運良く【】で囲まれてるので正規表現であっさり抽出することができた。 こんなコードを書いた。

import json
import re
import numpy as np
import matplotlib.pyplot as plt

def getListfromJson(filename, page = 1):
    """保存したjsonファイルから読み出し
    """
    tweets = []
    for p in range(page+1):
        with open("getData/" + filename +  "_" + str(p) + ".json", 'r') as fo:
            tweets.append(json.loads(fo.readline()))
    
    return tweets

def getWord(liststatus):
    """正規表現による文字列検索
    """
    scorelist = []
    pattern = r"【[0-9]*】"
    repatter = re.compile(pattern)

    i = 0
    for page in liststatus:
        if i != 0:
            page['statuses'].pop(0)#先頭が重複するため2ページ目以降は先頭削除

        for status in page['statuses']:
            i = i + 1
            text = str(status['text'])
            print("{0}: [{1}] {2}".format(i, status['user']['name'], text))
            search = re.search(repatter, text)
            #print(search)
            if search: #マッチしたときのみ
                index = search.span()
                print(text[index[0]+1:index[1]-1]) #数字のみ取得
                scorelist.append(int(text[index[0]+1:index[1]-1]))
    
    return scorelist


filename = "2017-10-27 0-53"
liststatus = getListfromJson(filename, 10)

#算出開始
scorelist = getWord(liststatus)

補足しておくと、jsonのファイルは1リクエスト1ページ最大100件。 タイムライン取得の際、2ページ目以降先頭が重複するので重複分を+1ページ追加で補っている。

計算結果とグラフの表示

スコアだけ集めた配列が出来たので、計算もできます。ついでにヒストグラムも作りました。 見たところ0から最大値230で5刻みの結果がでるようなのでbinsには230/5=46で綺麗に別れました。

print("\n")
print("有効ツイート数: ", len(scorelist))
print("平均値: ", np.mean(scorelist))
print("中央値: ", np.median(scorelist))
print("標準偏差: ", np.std(scorelist))

plt.hist(scorelist, bins=46, histtype="bar", rwidth=0.8, align='right')
plt.xlabel("Score")
plt.ylabel("Number of Tweet")
plt.title("#2017IQTest: Twitter User Score (2017/10/27 1000 tweets)")
plt.xticks(np.arange(0,235, 10))
plt.xlim(0,235)
#plt.legend()
plt.show()

結果

有効ツイート数:  993
平均値:  174.909365559
中央値:  180.0
標準偏差:  34.84813612

f:id:kitsune-gadget:20180421063326p:plain ということで面白い結果になりました。

平均値約175で中央値180…これ普通の人なら180くらいはスコア出せるということですね。 このスコアがIQの数値としてそのまま言われると無理があります。

平均と標準偏差からみると、スコア210以上のひとは褒めて良いと思います。

また、120以上に注目すると… f:id:kitsune-gadget:20180421063341p:plain 180あたりを中心とした正規分布に近い気がします。 こんな綺麗に出るとは思わなかった。 もう少し母数が多ければもっと正確にでるかも??

しかし、TwitterAPIはタイムラインに関して投稿日時の古いところをcount指定で連続取得しようとしてもある程度投稿された時期から過ぎてしまうと連続取得できないようになってるっぽいですね… 12月では300件程度しか連続で取得できなかった… ユーザーがいっぱい投稿してる時期のほうがこういうデータは集めやすいかもしれません。

ところで

このテストじゃ実際のIQ分からないの?って思うひともいるかもしれません。 ただ、推定は出来る気がします。

Wikipediaによると…

「同年齢集団内での位置」から算出した知能指数は標準得点で表され、中央値は100、標準偏差は15前後で定義されている。

知能指数 - Wikipedia

実際のIQ分布は中央値100で標準偏差15前後となっているみたいです。

もし今回の結果スコア180の部分がIQ100だとすると…標準偏差は計算結果から約30とみて…IQ分布の偏差が15なので今回のスコア分布は2倍の大きさで広がっていると仮定できます。 これらから、スコア160=IQ90, 180=IQ100, 200=IQ110, 220=IQ120... と言ったように推定出来るかもしれません。

とりあえず自分のテスト結果を参照してみてください、あなたの真のIQはそのあたりかもしれません???