Rでweb APIを使わずに5行で顔認識する

こんな話がある。 私は大人気ないのでRなら5行、いや実質3行だよとか言ってしまう。 以下はopencvパッケージのサンプルコードそのまま。

install.package("opencv") # インストール
library(opencv)
unconf <- ocv_read('https://github.com/dichika/ojisan/raw/master/teramonagi_001.jpg') #画像読み込み
faces <- ocv_face(unconf) #顔認識
ocv_write(faces, 'faces.jpg') #出力

f:id:dichika:20190704223130j:plain

まあOpenCV使えばどんな言語でもだいたい顔認識できるんじゃねえのって話。

化合物データの前処理をやりたい

化合物データの前処理をやる必要が出てきた。

ということである程度用語とかツールのイメージを把握しておきたい。

知ってる限りでとりあえず列挙。知りたいことを整理する。

 

1.化合物データのフォーマット確認:まずはSDFSMILESを覚えておけば良いか。

2.すぐ使えそうなデータの確認:Pubchemとか?

Rだとこの辺のパッケージを使ってデータを取ってくる。cdkrはCDKのラッパ。rJava依存なので怖い。

https://github.com/ropensci/webchem

https://github.com/CDK-R/cdkr

3.RDKitを使って作れる特徴量の確認:フィンガープリントとか?

https://qiita.com/muuu4649/items/7ef341f57bbea3988517

 

あーこれを読みながら一通り手を動かすのが一番手っ取り早いな。

https://github.com/Mishima-syk/py4chemoinformatics

CSVファイルを読み込む際「nullが埋め込まれている」とエラーが出た時はUTF-16LEを疑う

Windowsのもと作られたCSVファイルを読み込む際、CP932を指定しようというのは定石だが、それでもうまくいかないことがある。

エラーメッセージを読むと「nullが埋め込まれている」とある。

意味がわからない。

「nullが埋め込まれている」だから大方「R embedded null」あたりでググればなんかヒントあるだろと思って検索すると以下のSOがトップで出てくる。

stackoverflow.com

 

解決策を見ると、こういうファイルは大抵Windowsで作られたUTF-16LEのファイルだからそれを試してみろとある。

実際に試してみるとうまくいった。

 

ちなみにreadrパッケージのread.csv()でlocale = locale(encoding = "UTF-16LE")と指定してもうまくいかない。

ここに対応するのはなかなか大問題らしく未対応のようである。

 

github.com

いまどきの固定長データはread_fwf()を用いて読み込む

こんな感じのデータがあったとする。

library(readr)
fwf_sample <- readr_example("fwf-sample.txt")
cat(read_lines(fwf_sample))
John Smith          WA        418-Y11-4111 Mary Hartford       CA        319-Z19-4341 Evan Nolan          IL        219-532-c301

いわゆる固定長データであり、バイト数を指定して読み込むことになる。 Rだともともとread.fwf()という関数が用意されている。 https://dichika.hateblo.jp/entry/20120406/1333683931

が、いちいちバイト数を指定するのは面倒である。とにかく楽をしたい。データの読み込みなんぞで力を使いたくない。 空白のカラムからよしなにバイト数を推定して読み込んで欲しい。 こういう時はreadrパッケージのread_fwf()を利用する。

# 空白のカラムからよしなにバイト数を指定してもらうパターン
read_fwf(fwf_sample, fwf_empty(fwf_sample, col_names = c("first", "last", "state", "ssn")))

もちろんバイト数を指定するパターンも利用できるし、色々な指定法がある。

# バイト数を指定するパターン
read_fwf(fwf_sample, fwf_widths(c(20, 10, 12), c("name", "state", "ssn")))
# 上記を各列名と紐づけて指定するパターン
read_fwf(fwf_sample, fwf_cols(name = 20, state = 10, ssn = 12))

# 開始位置と終了位置を指定するパターン
# この場合、nameの開始位置は1 終了位置は20、ssnの開始位置は30 終了位置は42
read_fwf(fwf_sample, fwf_positions(c(1, 30), c(20, 42), c("name", "ssn")))
# 上記を各列名と紐づけて指定するパターン
read_fwf(fwf_sample, fwf_cols(name = c(1, 20), ssn = c(30, 42)))

いかがでしたか?

数字をアルファベットに変換したい時はchartr()を使う

数字をアルファベットに変換したい、もしくはその逆でアルファベットを数字に変換したいというときがたまにあります。

例えば、11, 12, 13 をAA, AB, ACに変換したいという時です。

こういう時はRではchartr()を利用します。

chartr("123456789", "ABCDEFGHI", 11:13)
[1] "AA" "AB" "AC"

第一・第二引数にそれぞれ対応表を与えて、最後に変換したいベクトルを与えるだけです。

0も加えて以下のような指定が楽かも。

chartr(paste(collapse="", 0:9), paste(collapse="", letters[1:10]), 11:13)
[1] "bb" "bc" "bd"

(追記)

確かにこっちの方が楽。

chartr("0-9", "a-z", 11:13)
[1] "bb" "bc" "bd"

いかがでしたか?

折れ線グラフで各系列にラベルをつける際はgghighlightを用いるのが楽なんじゃなかろうか

こういうデータがあるとする。

library(dplyr)
library(ggplot2)
library(gghighlight)
ChickWeight_diet <- ChickWeight %>% group_by(Diet, Time) %>% summarise(weight = mean(weight))
> ChickWeight_diet
# A tibble: 48 x 3
# Groups:   Diet [?]
   Diet   Time weight
   <fct> <dbl>  <dbl>
 1 1         0   41.4
 2 1         2   47.2
 3 1         4   56.5
 4 1         6   66.8
 5 1         8   79.7
 6 1        10   93.1
 7 1        12  109. 
 8 1        14  123. 
 9 1        16  145. 
10 1        18  159. 
# … with 38 more rows

折れ線グラフで各系列にラベルをつけたい。 いろいろやり方はあるが、gghighlightパッケージを用いるのが一番楽な印象。 gghighlight()の条件設定で全て該当するような条件を設定するのがポイント。 なお、筆者の環境はMacなので、日本語が文字化けするためlabel_paramsでMacの日本語フォントを指定している。

ggplot(ChickWeight_diet, aes(Time, weight, color=Diet)) + 
  geom_line() +
  gghighlight(max(weight)>0, label_params = list(family = "HiraKakuPro-W3"))

f:id:dichika:20190216193509p:plain

追記(2019/2/17) 開発者よりコメントいただき、条件設定は不要とのこと。

いかがでしたか?

Rで時刻の差をとるときは単位を指定する癖をつける(もしくはlubridate::time_length()を用いる)

時刻を入れたデータフレームがあるとする。

> smp <- data.frame(now=Sys.time(), then=Sys.time()-60) 
> smp 
   now                               then 
1 2019-02-09 10:30:15 2019-02-09 10:29:15 

で、時刻の差を計算すると、そこに単位も含まれてくる。

> smp$diff <- with(smp, now - then) 
> smp now then diff 
1 2019-02-09 10:30:15 2019-02-09 10:29:15 59.99999 secs 

これは煩わしいので、as.numeric()で数値に変える。

> smp$diff <- with(smp, as.numeric(now - then)) 
> smp 
    now                              then                              diff
 1 2019-02-09 10:30:15 2019-02-09 10:29:15 59.99999 

一見問題ないように見えるが、次のような時に困る。

> smp <- data.frame(now=Sys.time(), then=Sys.time()-3600) 
> smp$diff <- with(smp, as.numeric(now - then)) 
> smp 
   now                              then                                diff 
1 2019-02-09 10:38:55 2019-02-09 09:38:55 60 

これは時刻の差分を計算する時に呼び出されるdifftime()の引数unitsがデフォルトではautoとなっていることに起因する。 したがっていつも同じ単位で結果が欲しいときは、演算子ではなくdifftime()を用いて、unitsを指定するとよい。

> smp$diff <- with(smp, as.numeric(difftime(now, then, units = "secs"))) 
> smp                              
   now                              then                                diff 
1 2019-02-09 10:45:00 2019-02-09 09:45:00 3600 

もしくはlubridateパッケージでtime_length()を用いるという手もある。 こちらはデフォルトがsecsになっている。 なお、time_length()はIntervalクラスの値を求めるので、interval()してから渡してやる必要がある点に注意。

> smp$diff <- with(smp, time_length(interval(then, now))) 
> smp                              
   now                              then                                diff 
1 2019-02-09 10:45:00 2019-02-09 09:45:00 3600 

interval()の演算子として%--%も用意されているので、パイプを使いたいときはこちらもあり。

> smp <- smp %>% + mutate(diff = then %--% now %>% time_length()) 
> smp 
now then diff 
1 2019-02-09 10:49:53 2019-02-09 09:49:53 3600 

いかがでしたか????