R筋

プログラミング、金融、育児

【R】保育園スレを形態素解析してトピックを眺める

4月からの保育園が決まったものの、色々と準備が必要になるようで妻とネットを漁っている。
有名な掲示板にも、保育園準備にあたり先輩ママからの助言をきけるスレがあるようだ。

【センパイ】保育園入園&復職準備スレ 11【教えて】 [無断転載禁止]©2ch.net

保育園に持っていかないといけないものや、復職後こういう場合はどうするといった様々なケースにとても丁寧なアドバイスがかかれていて、こういうのがあると友達がいなくても生きていける現代社会は本当にありがたいものだなぁとしみじみ感じる。
とはいえ1000件の書き込みを全部読むのは大変だ。
そんなときは、形態素解析とwordcloudでトピックをざっと視覚化してみよう。

まず、形態素解析エンジンMecabをインストールする。
MeCab: Yet Another Part-of-Speech and Morphological Analyzer
その後Rで、XMLパッケージでスクレイピングし、
RMecabパッケージで形態素解析
wordcloudパッケージで視覚化という手順だ。

#パッケージロード
library(XML)
library(RMeCab)
library(wordcloud)
library(dplyr)

#掲示板を取得
html <- read_html("https://mevius.5ch.net/test/read.cgi/baby/1493387671/")

#掲示板のソースを見ると、書き込み内容はspanタグのclass='escaped'と
#なっているため、対象をxpathで抽出
node <- html_nodes(html,xpath="//span[@class = 'escaped']")

#htmlをテキストに変換
comment <- html_text(node)

#一旦ファイルに出力
write.table(comment,"comment.txt")

#形態素解析を実行
mecab <- docDF("comment.txt", type = 1)

f:id:anpontan382:20180212204551p:plain
1列目が単語、2・3列目が品詞、4列目が頻度となる。
意味不明なもの、記号や数字なども含めて6,700行あった。

#一般名詞、固有名詞だけを抽出
words <- mecab %>% filter(POS1 %in% c("名詞"), POS2 %in% c("一般","固有名詞"))

#wordcloudを描画
wordcloud(words$TERM,wores$comment.txt, min.freq= 7, scale=c(1,1),colors = brewer.pal(8,"Dark2"))

f:id:anpontan382:20180212210348p:plain
7回以上出現した単語をプロットしたが結果が多すぎて一部は表示されていない。その為、wordcloudを実行するたびに結果は変わる。

今回の結果からは、「Tシャツ」「ウインドブレーカー」「ストロー」「靴」「雨傘」「コップ」などについてはみんなが気にしてるものなので、考えとかないといけないようだ。

赤ちゃんの気持ちを知るには

僕の息子もまもなく6ヶ月になる。少し前にブカブカだった服がもう着れなくなっていたり、僕が帰宅するとキャッキャ言って喜ぶようになったと思ったら、人見知りなのか「う~」と唸るようになる時期もあり、かと思ったら最近はまたニコニコしてくれるようになったりと、この6ヶ月で本当にめぐるましく心身が変化していることがわかる。

体の成長は見ればわかるが、まだ言葉を話して意思表示ができないので、心の変化はある程度、想像が必要となる。なぜ、笑ったのか、泣いているのか、怒っているのかを推察し、いないないばぁをしたり、寝かせたりといったことを親はしなくてはならない。

とはいえ、赤ちゃんの気持ちを理解するのは非常に大変だ。最近妻は仕事復帰を見据え、母乳から哺乳瓶へ変えようとしたが、なかなか飲んでくれず、様々な哺乳瓶を試しては、なんでだめなんだろうと悩んでいた。根気強く飲ませ続けたところ、哺乳瓶で飲めるようになったが、息子にどういう心境の変化があったのかはよく分からない。

そんな中で「赤ちゃんの気持ち」なんて検索しているとこんな記事を見つけた。

関心したのは次の部分。

あるときぼくも別のスタッフと「赤ちゃんの気持ちになってみよう」ということで、いろんなものを口に入れてみました。なかでも凄かったのは振動子で、手のひらでささやかに感じる程度の「ブルブル」は、口に入れてみると歯をガタガタ言わせるし、口いっぱいに振動が広がるし、わ!!!すご!!となりました。直感では手の触力(そんなものはない)が10だとすると、口の触力は100だなという感じ。なるほど、みんながモノを口に入れようとするのは、そのほうが情報がたくさん入ってきて面白いからだ、ということに気がつきます。 

僕は大人の視点で、寝ている赤ちゃんを見下ろしながら、「赤ちゃんが」何を考えているのか勝手に解釈していたが、赤ちゃんと同じ条件で、見て聞いて触れたときに、「僕が」何を考えるかというのはとても意味があるのではと考えた。

注意してほしいのは、僕は決して赤ちゃんプレイに興味があるわけではない。前述までのものすごく全うで自然な理由から、哺乳瓶を使ってみる必要があった。

f:id:anpontan382:20180211230305p:plain

妻にもう使わない哺乳瓶を貰い、粉ミルクを溶かして、吸ってみた。真っ先に感じるのは、「飲みづらっ!」ということだ。

哺乳瓶には、直径1mm程度の穴しかあいておらず、吸い出すために乳首部分を吸う必要があるが、口を開けすぎても閉じすぎてもうまく吸うことが難しくなるため、乳首のサイズちょうどに口を開いて固定しなくてはならない。また吸う力も、強すぎると唇が巻き込まれて痛いし、弱すぎると何も出てこない、一定の量を常に出すにはこれもコツが必要だ。また哺乳瓶が真上を向いているときは自然に垂れてくる分がある。大人に飲まされる場合、数滴であるが自分のペースを乱されることになるだろう。また、これは赤ちゃんには関係ないかもしれないが粉ミルクは不味い。ずっと飲んでいると吐きそうになる。自分で飲むなら嫌になったらやめればいいが、赤ちゃんは強制的に飲まされるわけで、粉ミルクの味が気に入らなかったら絶望的な状況だろう。

そんなわけで300ミリを試行錯誤しながら10分以上かけて飲み干した僕は、こりゃ簡単に飲めるもんじゃねぇなという結論に達した。息子が哺乳瓶で飲めるようになるために妻は四苦八苦していたが、息子も同時に大変な苦行だったのだろう。

これからよく言われるヤダヤダ期というのが来て、いろいろなことがうまく進まないかもしれない。それを大人の視点で、「こんな簡単なことも出来ないのか」と思ってはいけないのだ。赤ちゃんの境遇でその問題に向かってみると、本人にとってそれが出来ないものすごく重大で深刻な理由があることがわかるかもしれない。

僕はこれからも真剣に、おむつを履いたり、ハイハイしたりして、息子の気持ちを理解できるよう努める所存である。

 

【python】bitflyerのAPIを操作 public API・chat編

コインチェックの流出事件から1週間がたちました。この事件を発端にネム以外の仮想通貨も乱高下しています。世の中の大半はそこまで混乱していないみたいですが、コインチェックにお金を預けていた人はもちろん、コインチェック以外の取引所でも仮想通貨の取引をしている人達はまだまだスリリングな日々を過ごしていることでしょう。
bitflyerのチャット履歴を取得して関係各位の混乱を確認いたしましょう。

今回は、チャットに様々な文字列が入ってくるせいで、Rを使うとエラーが起きやすくpythonで取得することにしました。pythonはpybitflyerというbitflyeAPIを簡単に取得できるパッケージがあるため、こちらを使います。

import pybitflyer
api=pybitflyer.API()
chat = api.getchats()
print(chat)

[{'nickname': '実穂ノア♚world🍀LOVE💑', 'message': '皆で稼ぐw', 'date': '2018-01-30T01:29:43.68'}, {'nickname': 'はじめてのお取引', 'message': 'おわりじゃああビットのおわりじゃあ', 'date': '2018-01-30T01:29:44.993'}, {'nickname': '利確', 'message': '現物', 'date': '2018-01-30T01:29:45.92'}, {'nickname': 'こころぴょんぴょん🐰', 'message': 'ぴょぴょんぴょん🐰', 'date': '2018-01-30T01:29:46.793'}, {'nickname': '大根38円', 'message': 'mecyべえww', 'date': '2018-01-30T01:29:48.607'}, {'nickname': 'からだすこやかちゃ〜', 'message': '濃いや', 'date': '2018-01-30T01:29:50.08'}, {'nickname': 'Lチキン', 'message': 'Low', 'date': '2018-01-30T01:29:53.083'}, {'nickname': 'てやんでぃ', 'message': 'あがるパワーはない', 'date': '2018-01-30T01:29:55.963'}, {'nickname': 'みどり🍀', 'message': 'てかリバるんかこれ?www', 'date': '2018-01-30T01:29:56.09'},......

こちらもjson形式で、発言時間、名前、発言内容がとれます。
途中で省略しましたがパラメータを指定しない場合5日前からの発言を取得しますので40メガバイトほどのデータでした。
pandasで整形しています。

import pandas as pd
chat2 = pd.DataFrame(chat)

f:id:anpontan382:20180204120414p:plain
f:id:anpontan382:20180204120453p:plain

5日間で30万件のデータでした。
うーむ内容ゼロ!

コインチェック”,"coincheck","CC"の文字列を含む発言を取り出します。

chat2[chat2["message"].str.contains('コインチェック')|chat2["message"].str.contains('coincheck')|chat2["message"].str.contains('CC')]

f:id:anpontan382:20180204121527p:plain

3,772件でした。
5日間の全履歴の内、約1%はコインチェック関連の発言ということですね。

ちなみに、一番書き込みしている人は誰かを調べてみましたら、

chat2["nickname"].value_counts()

いなごflyer 6105
First order 2913
スキャルプD@バイオプ 2573
チョレイ 2517
☺🐰🐈 Sofia🕊@sofia_bitfx🐮🐻@ピコ 2435

「いなごflyer」さんが圧倒的なコメント量でした。
気になって「いなごflyer」で検索すると、こんなサイトが
inagoflyer.appspot.com
どうやら世界中の取引所の売り数量・買い数量を比較できるようです。取引所ごとにAPIを取得しなくても、すべて見れるというのが凄いですね。また、一定のボリュームを超えたときに音で教えてくれるみたいです。
これを見ながら一気に大きな圧力がかかった方向に便乗する短期売買をしてみるのも楽しいかもね。

家庭内LAN楽しいなランランラン♪

先日の記事

で、スマホアプリのベビーモニタを使ってみたものの、有料だわスマホのカメラじゃ暗闇だと何も訳に立たんわでほとんど実用性はありませんでした。しかし僕は赤ちゃんが寝た後どうしても別室で自由を謳歌したく、結局、暗闇でも使えるネットワークカメラをポチってしまったのでした。

 早速wimaxルータに接続してみるとこいつはすげぇ!赤外線カメラなので暗闇の中でも赤ちゃんの目が開いているか閉じているかまではっきりわかるではありませんか。

またこれは動きを感知する機能があり、常にモニターしていなくても赤ちゃんが動いたときは通知で教えてくれるため、夜中に起きてもすぐに教えてくれるのです。

そんなわけで僕は7,000円で自由を手に入れました。

手に入れた自由時間に僕は考えました「ネットワークカメラって凄いなぁ~楽しいなぁ~もっと色々なものをネットワークにつなげたいよおおお!!!」そして気がつくとルーターをポチっていました。

BUFFALO 11n/a/g/b 300プラス300Mbps 無線LAN親機 WZR-600DHP3

BUFFALO 11n/a/g/b 300プラス300Mbps 無線LAN親機 WZR-600DHP3

 

 これでいろいろと楽しいことができるようになったわけですが、ひとまず我が家のネットワークの全体像を示すとこんな感じです。

 

f:id:anpontan382:20180121230150p:plain

 

活用例を何点かご紹介します。

NAS

ルーターを選ぶ上で重要だったことはUSBストレージがあることで、データバックアップ用に買った3Tの外付けHDDがあるんですが、有線を都度PCに接続してバックアップを取るということが面倒なため、ほとんど使われずに放置していました。

この度ネットワークストレージとして復活を遂げ、家庭内の各端末からのアクセスが可能となったため、バックアップのみならず妻との共有フォルダ、動画のストリーミング視聴などが気軽にできるようになりました。

②ネットワークカメラ

前述の商品です。アプリを導入することで、PC、スマホから視聴ができるようになります。またこの商品の凄いところは、インターネット上のクラウドにも送れるため外からスマホでカメラの映像を確認することもできます。

リモートデスクトップ接続

使わなくなったPCのIPを固定しリモート接続し、さらにwi-fi機能がないテレビと接続してみました。使いみちは今のところ未定です。このPCから、自分で撮った赤ちゃんの画像をテレビに流したりすることを考えています。

将来的には、ポートを開放して自宅サーバにしたいなぁ。

 

この図の他にも妻のPC、スマホタブレットなど10以上の機器をネットワークにつなぎ、トラフィックを監視しながらニヤニヤしています。

今後やってみたいこととはこんな感じです。

・スキャナーで重要書類をスキャンして共有ストレージに保存する。

・外から自宅サーバからキックしてgoogle homeを喋らせる

スマート家電も赤外線家電もGoogle Homeでまとめて操作 - Qiita

Raspberry Pi

などなど。

必要な機器を取り揃えたら果たしていくらかかるかな…自由の代償はでけぇなぁ

【R】bitFlyerのAPIを操作 public API・ticker編

過去のブログで板情報を取得しました。
anpontan382.hatenablog.com
今回はティッカー情報です。
ティッカー情報は、取得時点のベストプライス・ボリュームなどです。自動売買ツールを作る上では条件判定に必要になるでしょう。
早速コードはこちら~

#最初は前回同様です
#ライブラリロード
library(rjson)
library(RCurl)

#エンドポイントを設定
endpoint <- "https://api.bitflyer.jp/v1/"

#パラメータに対応
getboard <- paste(endpoint,"getticker?product_code=BTC_JPY",sep="")

#tickerを蓄積するデータフレームを作成
ticker_DB <- data.frame(matrix(rep(NA, 12), nrow=1))[numeric(0), ]
colnames(ticker_DB) <- c("product_code","timestamp","tick_id","best_bid","best_ask",  
                          "best_bid_size","best_ask_size","total_bid_depth","total_ask_depth","ltp",              
                          "volume","volume_by_product")

#1000回取得します
for (i in 1:1000){

  #json→リスト変換→data.frame
  json <- getURL(getboard)
  ticker <- fromJSON(json)
  ticker <- as.data.frame(ticker)

  #0.1秒待つ(bitFlyerへのアクセスは1分間に200回が上限です)
  Sys.sleep(0.1)

  #取得したtickerを格納
  ticker_DB <- rbind(ticker_DB,ticker)
}

1000行のティッカー情報が取れました。
f:id:anpontan382:20180115224605p:plain

timestampは世界標準時UTC)のため、日本時間(JST)にすると
2018-01-15 22:27:44から10分間のデータになります。

f:id:anpontan382:20180115225337p:plain
サマリーを見てみますとこの5分間の間は、ltp(最終取引価格)が170万8千円~171万3千円で推移したことがわかります。この5分でうまくやれば5,000円手に入ったわけだ。

plot(ticker_DB$ltp,type="l")

f:id:anpontan382:20180115230551p:plain
プロットするとこんな感じ。
よーしそれじゃ早速タイムマシンで22:27:44に戻ってみんなも5000円ゲットじゃぞ~

【R】主成分分析でベビーカーを分類

主成分分析とは、色々な項目で計測されているサンプルに対して、主成分と呼ばれる新しく合成した少数の尺度を使って分析する手法です。
例えば、BMIは身長と体重から算出される肥満度を表す指標ですが、これがあることで、1つの指標だけで複数のサンプルを比較することが容易になります。
スマホのスペックには、バッテリー容量、画面解像度、重量、バイブの強さがあるとします。これらから主成分を抽出する場合、バイブの強さはあまりスマホによって変わらないので、情報量が少ない(分散が少ない)ため、尺度を減らす上で捨てられることになりそうです。またバッテリー容量と重量は相関がありそうなため、一つにまとめて新たな尺度にできるのではないでしょうか。
このような形で、スマホのスペックをいくつかの尺度で説明することで、特徴を把握し、機種の分類に役立てます。

主成分分析は次の流れで行います。
1)分散共分散行列(相関行列)を作成する
分散共分散行列→各計測値の単位が同じときに使用
相関行列→各計測値の単位がバラバラの場合に標準化できる
2)主成分を求める
分散共分散行列(相関行列)から固有値ベクトルを算出する

Rでは標準でprcomp()関数が用意されており、上記の計算をまとめて実施してくれます。レッツトライ!

あまりいい例になりませんでしたが、妻のブログでベビーカーのスペックをまとめていたので、この主成分分析を行います。
adijo.hatenablog.com

商品毎に、価格、重量、カゴ容量を表にした
babycar.csvを作りました。
f:id:anpontan382:20180108164332p:plain

#取り込み
library(readr)
baby <- read_csv("~/babycar.csv")
baby <- as.data.frame(baby)
#商品名を列名に設定
rownames(baby) <- c(baby$product)

#商品名以外を再度取り出し
baby <- baby[,2:4]

#主成分分析を実行
#scale=Tは相関行列での計算
result <- prcomp(baby,scale=T)

 summary(result)
#Importance of components%s:
#                         PC1    PC2    PC3
#Standard deviation     1.2063 0.9330 0.8212
#Proportion of Variance 0.4851 0.2902 0.2248
#Cumulative Proportion  0.4851 0.7752 1.0000

Proportion of Variancとは、各主成分の寄与率を表し、
Cumulative Proportion とは、累積寄与率を表します。
各主成分の寄与率とは、その主成分で全体のどれだけを表せるかを示しており、
第1主成分~第N主成分までで、全体のどれだけを表せるかの表示となります。
今回のケースでは第2主成分までで77%を説明できることになります。
一般的にも70%を超えるまで主成分を取り出すことが目安になっています。

resule$rotation
#               PC1        PC2        PC3
#price    0.6385902 -0.1918353 -0.7452528
#weight   0.5982140 -0.4854510  0.6375557
#capacity 0.4840895  0.8529575  0.1952457

$rotationが主成分を表す固有ベクトルです。

result$x
#                            PC1        PC2         PC3
#Runfee ef            -1.3555083 -0.3347032  0.34179979
#PATTAN               -1.3742207  0.5686794  0.51548585
#Premige               0.6631685 -1.2076507 -0.84968911
#MECHACAL HANDY       -0.3616031 -0.1325712 -0.96859595
#NEMURIE               0.4879116 -0.5742262 -0.12697994
#LUXUNA Comfort        1.2294453  1.2064958 -0.98609744
#SMOOOVE premium       1.7452139  0.9801604  1.16819540
#magical air plus     -1.5209180  0.7904333 -0.08955709
#Air Buggy COCO BRAKE  0.4865108 -1.2966176  0.99543849

$xは主成分得点と呼ばれます。
Σ各固有ベクトル×各計測値で算出され、
固有ベクトルによって描画するにあたり、その座標の意味を持っています。

cor(result$x,baby)
#         price     weight  capacity
#PC1  0.7703448  0.7216382 0.5839673
#PC2 -0.1789771 -0.4529125 0.7957860
#PC3 -0.6119936  0.5235539 0.1603336

主成分と計測値との相関係数を求めることで、主成分負荷量を算出します。
この数値が大きいほど、各変数が主成分に与える影響力が大きいことを表します。
この例では、第1主成分と相関が高いのは同じ位で、price,weightで第2主成分ではcapacityです。

biplot(resule,choices=c(1,2))

f:id:anpontan382:20180108210607p:plain
biplotは個体と変数を重ねて主成分空間上に描画します。

この図を見ると、価格・容量が高い「ラクーナコンフォート」「スムーブ」グループと、重量・価格が高い「Premige」「エアバギー」グループ、安い「PATTAN」「マジカルエアープラス」グループがあることがわかります。

重量と容量などは似た数値なので、この例だとイマイチ結果から言えることが少ないですが、「走行性」「安全性」「重量」などそれぞれ異なる項目をうまいこと数値化できると、それぞれの性質ごとにグループ分けすることができそうですね。このくらいの商品数なら全部の数値を見ていっても自分にあったベビーカーを選ぶことはできそうですが、もしベビーカーが1,000種類位あって、そのデータが全部取れて入れば、まず主成分分析をして、自分が重視する商品グループ決めた上で、その中で一番合っている商品を選ぶみたいな活用ができるかもですね。

Google HomeとTwitterの連携が意外と楽しい!

 先日の記事、

 で、Google HomeTwitterの連携をしましたが、このGoogle HomeからTwitterを更新するのが、意外と楽しくて、このブログをPCで見たときのサイドバーにもTwitterのタイムラインを載せちゃいました。

細かい点ですが、いくつか改良を加え使い勝手を良くしたので、その辺をご紹介します。かなり縦長ですが、こちらがTwitterGoogle Homeを連携するIFTTTの設定画面。

f:id:anpontan382:20180107200434p:plain

①What do you want to say?

にはGoogle Homeでトリガーとなる発言を登録しますが、optional2つと併せて3つまで設定可能です。「twitter○○」「twitterに○○と投稿して」「twitterに○○と書く」の3つを投稿していますが、「投稿する」とか「書いて」とかみたいな微妙な違いでも投稿できないため、「twitter○○」が一番使い勝手が良いです。

Tweet text

には実際にツイートする文章を設定します。「TextField」がGoogle Homeに話した言葉ですが、それ以外にも、「 -from Google Home #2017aug_baby」というのを設定しました。

「 -from Google Home」をつけたのは、Google Homeが聞き間違いをしたりして意味不明のツイートをした場合、責任の所在はGoogle Home にあることを明確にするためつけました。それと当然だけど赤ちゃん語は、Google Homeが聞き取れないので、息子が「アンギャー」と言ったときに、それをツイートしようとしたら、こうなりました。

「ギャッギュ」と言ったときはこう。

そんな感じでわけわからん発言が多いので、悪いのはGoogle Homeですよというアピールですね。

「#2017aug_baby」は、同じ月齢のママ友作りのためのハッシュタグに使われることが多いらしいという話を妻から聞いたのでつけました。このハッシュタグから見に来た人がいたとしても、他のツイートが意味不明すぎてママ友になってくれないだろうけどね。

 

ともあれ、僕からでも妻からでも「OK google」でツイッターに息子の成長での気づきを書き込めるので、妻も事あるごとに「OK google」しています。

 

デメリットとしては、過去のツイートも3回に1回位は「うまく聞き取れませんでした」というエラーです。また長文だとほとんどエラー。この辺はもう少し精度が上がってくれると日記のような使い方もできるのかなぁ。

とはいえ今の感じでも、あとから見直したら楽しいものになりそうです。これからも普通の毎日をマメに記していきたいと思います。