clojureで自分のツイートを触ってみた
このごろclojureを始めたのでその練習に自分のTwitterのつぶやきをいろいろなライブラリを使っていじくってみました.
つかったライブラリはkuromojiとかincantereです.
とりあえずデータはTwitterのアカウント->ユーザ情報の下の方に全ツイート履歴というのがあるのでそこから取ってくる.
今回やったことは以下の3つです
- 月別のツイート
- 時間別のツイート
- よくツイートしている単語
準備
プロジェクトを作成する
lein new twitter
cd twitter
./project.clj
を以下のように書き換える
(defproject twitter "0.1.0-SNAPSHOT" :description "FIXME: write description" :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} :dependencies [[org.clojure/clojure "1.5.1"] [incanter "1.5.4"] [clj-time "0.6.0"] [org.atilika.kuromoji/kuromoji "0.7.7"]] :repositories [["Atilika Open Source repository" "http://www.atilika.org/nexus/content/repositories/atilika"]] :main twitter.core :aot :all)
依存しているライブラリをよむ
lien deps
./twitter/core.clj
に以下を追加
(ns twitter.core (:require [clojure.pprint] [net.cgrand.enlive-html :as en] [clojure.string :as str] [clojure.test :as te] [clj-time [core :as ct] [format :as ft]]) (:import [org.atilika.kuromoji Token Tokenizer]) (:use (incanter core charts stats io datasets pdf)) (:gen-class)) ;データ (def resource (read-dataset "tweets.csv" :header true))
(read-dataset)
はincanterというライブラリの関数でcsvを読んでくれる.
月別ツイート
./twitter/core.clj
に以下を追加
(defn remove-day "年月日から日を取り除く" [ymd] (let [[y m _] (str/split ymd #"-")] (str y m))) (defn year-month-day "年月日を取り出す" [timestamp] (let [[ymd _ _] (str/split timestamp #" ")] ymd)) (defn year-month "年月を取り出す" [timestamp] ((comp remove-day year-month-day) timestamp)) ; (year-month "2013-02-06 15:31:33 +0000") ;=> 201302 ;月別のツイート数 (let [data (->> ($ :timestamp resource) (map year-month) frequencies sort)] (view (bar-chart :time :count :data (dataset [:time :count] data))))
Twitterから撮ってきたcsvのタイムスタンプが2013-02-06 15:31:33 +0000
こんな感じ.
そこで,year-month
を定義して年月を取り出しfrequencies
でそれぞれの頻度を求めて最後にソートする.
そしてincanterのbar-chart
を使用してグラフにする.
x軸の他多くの要素があると文字が潰れてしまうのですが直し方がわからず放置しました.
時間別ツイート
./twitter/core.clj
に以下を追加
(defn get-time "時分秒を取り出す" [timestamp] (let [[_ time _] (str/split timestamp #" ")] time)) (defn hour "時分秒から時を取り出す" [time] (let [[hour _ _] (str/split (get-time time) #":")] hour)) ; (hour "2013-02-06 15:31:33 +0000") ;=> 15 ;時間ごとのツイート回数表示 (let [data (->> ($ :timestamp resource) (map hour) frequencies sort)] ;データ作成 (view (bar-chart "time(h)" "count" :data (dataset ["time(h)" "count"] data)))) ;表示
こちらはhour
を定義して時間を取り出しfrequencies
でそれぞれの頻度を求めて最後にソートする.
最後にincanterの関数bar-chart
で結果を表示.
よくツイートしている単語
./twitter/core.clj
に以下を追加
この部分はClojure/kuromojiでテキストマイニング入門 ~形態素解析からワードカウントまで~を見てやったのでそっちのほうがわかりやす位と思います.
(defn get-tokenizer "受け取った文字列のtokenizeをかえす" [str] (let [^Tokenizer get-tokenizer (.build (Tokenizer/builder))] (-> get-tokenizer (.tokenize str)))) (defn noun [str] (letfn [(noun? [str] (= "名詞" str)) (split-first [str del] (first (str/split str del)))] (for [toke (get-tokenizer str) :when (noun? (-> toke .getAllFeatures (split-first #",")))] (.getSurfaceForm toke)))) (defn disuse? [str] (let [dic #{"Y" "ん" "の" "/" "\\" "(" ")" "." "^" "これ" "こと" "あと" "#" "-" "ー" "30" "それ" "\\\"" "さ" "thou" "\"" "1" "2" "3" "4" "5" "6" "7" "8" "9"}] (not (contains? dic str)))) ; ツイート頻度の高い単語の上位N件をとる (view (letfn [(url-reply [s] (str/replace s #"@\w+|https?://[\w/:%#\$&\?\(\)~\.=\+\-]+|@\w+" ""))] (->> ($ :text resource) (map url-reply) (map noun) flatten (filter disuse?) frequencies (sort-by last) reverse (take 30))))
リプライを消すために正規表現を書いたり,明らかにおかしいものを弾くように辞書っぽいものを作ったりしました. 一人称が"俺"で"ww"と”笑”と"www"などが笑いの表現が統一されていないということくらいしかわからないというつまらない結果になりました.