niszetの日記

細かい情報を載せていくブログ

(R) ggplot2のデフォルトの設定を探していく。まずは色から。

デフォルトの設定を探すのは思った以上に大変ですよコレ

元ネタはこちら。

qiita.com

この色、どこで設定されているんでしょう?って気になったので、調べてみると、

asNamespace("ggplot2")[["scale_color_continuous"]]

の中身が

function (..., low = "#132B43", high = "#56B1F7", space = "Lab", 
    na.value = "grey50", guide = "colourbar") 
{
    continuous_scale("colour", "gradient", seq_gradient_pal(low, 
        high, space), na.value = na.value, guide = guide, ...)
}
<environment: namespace:ggplot2>

となっており、連続値のときの色が引数のデフォルト値に入っていますね。

この関数の実体はseq_gradient_pal()なので、実際に、下記のように与えると、

scales:::seq_gradient_pal(low = "#132B43", high = "#56B1F7", space = "Lab")(seq(0,1,1/24))

#>  [1] "#132B43" "#15304A" "#183550" "#1B3A57" "#1D3F5E" "#204465" "#22496C" "#254F73" "#28547A" "#2A5A82" "#2D5F89"
#> [12] "#306590" "#336A98" "#3670A0" "#3875A7" "#3B7BAF" "#3E81B7" "#4187BF" "#448DC6" "#4793CE" "#4A99D6" "#4D9FDE"
#> [23] "#50A5E7" "#53ABEF" "#56B1F7"

のように得られて、上記のページのカラーコードと一致することが確認できました。

同様に、discreteの方は

asNamespace("ggplot2")[["scale_color_discrete"]]

function (..., h = c(0, 360) + 15, c = 100, l = 65, h.start = 0, 
    direction = 1, na.value = "grey50") 
{
    discrete_scale("colour", "hue", hue_pal(h, c, l, h.start, 
        direction), na.value = na.value, ...)
}
<environment: namespace:ggplot2>

から、

scales::hue_pal(c(0, 360)+15, 100, 65, 0, 1)(4)
#> [1] "#F8766D" "#7CAE00" "#00BFC4" "#C77CFF"

となって、例とカラーコードが一致しますね。

ヒストグラムの灰色はgrey35かなぁ。このgrey35って値自体が使われていることは確認できたけど…デフォルトの挙動はまだ謎が多い…。

github.com

最近ようやくggplot2パッケージの中が追えるようになってきたのですが、果たして私が進むべき道はこっちなのだろうか…違う気はしている…。

まぁとりあえずわかったことは以上です。

Enjoy!!

(R) x軸共通の場合に、列名が条件に合致した場合に全部y軸にプロットする (メモ)

簡単だけど、そのものずばりが見つけられなかったので。

とりあえずirisで。x軸は適当にindexを振っておいて、これを共通の軸とする。y軸方向にはSpecies(とid)を除いた全部をプロットしたいので、列名に"."が含まれているものを取り出してプロットする感じで。

とりあえず捻りのないやり方で…。

library(ggplot2)
library(magrittr)
library(dplyr)

# id振っておく
iris_ <- iris %>% mutate(id=row_number()) 

# 下地を作っておく
g <- ggplot(iris_, aes(x=id))

# 列名に条件を設けて取り出す。
coliris <- iris %>% select(contains(".")) %>% colnames()

# for文でまわす
for(i in coliris){
  g <- g + geom_point(aes_(y=as.symbol(i), color=as.factor(i)))
}
g <- g + ylab("Value") + scale_color_discrete(name="column")
# ggplot2:::print.ggplotでplotする。何か設定を追加するならこの前に。
g

これで、

f:id:niszet:20180327234150p:plain

こんな感じ。個人的には使う機会が多くなりそうなのでメモ。

この書き方で、色はちゃんと別々になるんだなぁ…

追記

コメントとTwitterのそれぞれで、あ~る・芸人一郎さんとAtsushiさんによりスマートな書き方を教えていただいたのでご紹介。

あ~る・芸人一郎さんのコードは、

require(tidyverse)
iris %>% 
dplyr::select(dplyr::contains(".")) %>% 
tibble::rowid_to_column("id") %>% 
tidyr::gather(key = key, value = value, -id) %>% 
ggplot2::ggplot(ggplot2::aes(x = id, y = value, colour = key)) +
ggplot2::geom_point()

Atsushiさんのコードは

library(dplyr)
library(tidyr)
library(ggplot2)
ggplot(
  iris[-5] %>%
    mutate(id = row_number()) %>%
    gather(column, Value, -id),
  aes(x = id, y = Value, color = column)
) +
  geom_point()

です。gatherを使えばaesでいけるんですね~。あ~る・芸人一郎さんのコードではtibble::rowid_to_column()でid列を追加していて、こういう便利関数は色々あるはずなのだけど全然追い切れていない…。
Atsushiさんのコードのように、ggplot()の関数の呼び出しの引数内でも %>% が使えます(最終的に評価されたものがggplotに渡る)

近いうちにgather()使いこなしのための記事を書かないといけませんね…!

あ~る・芸人一郎さん、Atsushiさん、ありがとうございました。

(他にもあるぞ!という方、まだまだ募集中…!)

追記の追記

Atsushiさんから、私のfor文を使っているコードのapply版もいただきました。やっぱりapply系の関数に置き換えるとスッキリしますね。
最近無理にapply使おうとして時間を無限に溶かしたので苦手意識が再燃…。こちらも頑張るぞい💪

# id振っておく
iris_ <- iris %>% mutate(id=row_number())

# 列名に条件を設けて取り出す。
coliris <- iris %>% select(contains(".")) %>% colnames()

ggplot(iris_, aes(x=id)) + 
  lapply( #レイヤーのリストが返る
    coliris, 
    function(i) 
      geom_point(
        aes_(y=as.symbol(i), color=as.factor(i))
      )
  ) +
  ylab("Value") + 
  scale_color_discrete(name="column")

Enjoy!!

(R) ggplot2パッケージでbode線図を描くための設定暫定版

あまり捻りがないですが…

これ

niszet.hatenablog.com

の続きです。

library(ggplot2)
library(magrittr)
library(sitools)


# define lpf function
lpf <- function(freq, R, C, ppd=20) {
  from_freq <- freq[1]
  to_freq <- freq[2]
  freq <- 10 ^ (seq(log10(from_freq), log10(to_freq), 1 / ppd))

  w <- 2 * pi * freq
  v <- 1 / (1i * w * C * R + 1)
  data.frame(list(x = freq, y = abs(v), s = atan2(Re(v), Im(v)) / pi * 180))
}
 

hogehoge_plot <- function(tmp, ycol, xlim=NULL) {
  
  breaks_x <- NULL
  minor_breaks_x <- NULL

  if (!missing(xlim)) {
    idx <- (floor(log10(xlim[1])) - 1):(ceiling(log10(xlim[2])) + 1)
    breaks_x <- 10 ^ idx
    minor_breaks_x <- rep(1:9, (idx[length(idx)] - idx[1] + 1)) * (10 ^ rep(idx, each = 9))
  }

  tmp %>% 
  ggplot(aes_(
      x = quote(x), y = ycol
    )) +
    geom_point() + geom_line() +
    (if(missing(xlim)) {scale_x_log10(labels = sitools::f2si )} else  {scale_x_log10(breaks = breaks_x, minor_breaks = minor_breaks_x, limits =  xlim, labels = sitools::f2si)}) +
      # 10のべき乗の書式が良ければ下記。しかし字が小さくて微妙。
      #breaks = trans_breaks("log10", function(x) 10 ^ x),
      #labels = trans_format("log10", math_format(10 ^ .x))
    scale_y_continuous(
      # 縦軸はどうするかね…
    ) +
    annotation_logticks(sides = "bt") + # size, short, long, mid について設定が出来るが、固定値だと厳しい…。
    theme(plot.title = element_text(size = 8), axis.title = element_text(size = 8)) +
    theme(
      panel.grid.major = element_line(size = 0.3, colour = "grey70"),
      panel.grid.minor.y = element_line(size = 0.1, color = "grey80", linetype = "solid"),
      panel.grid.minor.x = if (missing(xlim)) {
        element_blank()
      } else {
        element_line(size = 0.1, color = "grey80", linetype = "solid")
      },
      panel.background = element_rect(fill = "white", colour = "black")
    )+
    xlab("Frequency(Hz)") + 
    ylab("Magnitude")
}

# sample lpf object for bodeplot
tmp1 <- lpf(c(10, 1e9), R = 1000, C = 1e-9) # %>%

hogehoge_plot(tmp, ycol = quote(y), xlim=c(4e3, 6e8))

これの実行結果はこんな感じね。

f:id:niszet:20180327003032p:plain

grid周りが綺麗に描けると満足感ある。ただ、colorや、legendはまだ改良の余地がある。とりあえず暫定ではこんな感じかな。

missing(xlim)まわりはちょっと悩み中です。xlim与えないとminorのgridが表示されないとか、軸の目盛りの表示が荒くなるとかしてしまう。
いっそmissingしないで暫定値与えれば良いのでは?というのと、ggplot2パッケージは一体どのようにしてplot領域のmin-maxを決めているのかがわかればそれを使えると思うので、その辺りで改良していく予定。

あと、y軸がmagnitudeなのはlogじゃない軸を書いてみたかったからです。20log10か10log10されたものを表示させる前提でも良いかもしれない。complexで与えられる前提とか。
aesとNSEまわりも良く分からないのでもうちょっと調べないと…。軸に使う変数を与えるにはaesしかないと思うのだけども…。

あと、annotation_logticksはlog scaleになっていない軸に設定しようとすると、20GB(これは規模による)くらいのメモリを確保しに行ってコケます。どういう挙動なのか不明ですが、軸の設定をいじるときは注意で。あと、一部設定によっては引数群の末尾に,があっても動作してしまいますが、基本はNGだと思っていた方が良いです。無限に時間を溶かしました。

何気にxlimの前処理部分が個人的には便利で、breaksが中途半端な値を与えられるとgridが予期しない位置に出てくることを避けられます。もうちょっと良い方法があるかもしれないけど…

あとはcolorとかshape周りでscale_color_discreteとscale_shape_manualを外部から設定できるようにしたいなー…とか、titleとかthemeのまだ設定したことがない項目も触っていきたい。

これらの設定をデフォルトで持っているパッケージというかお便利関数が欲しいので作ろうかなーと思っている次第です。昔、geom_bodeってのを作ろうと思っていたのですが、geomにはthemeがないからダメだな…と思っていたけど、ggternを参考にやってみようと思います。

またもAtsushiさんに助けていただきました。ありがとうございます!

久々(?)の凄い乱文ですが、文章推敲する余裕がない…。いずれ更新します。

Enjoy!!

(R) ggplot2で対数軸つかいはじめて、色々と詰まったのでデフォルト設定を詰め込みたい。

だんだんと、細かい設定、したくなる…。

さて、お仕事でRを使うために、ggplot2パッケージを活用して、データを見やすくまとめています(予定)

お仕事的にはx軸を対数表示にすることが多くて1、今は主にその辺りで苦戦中…。 しかしまぁ、SOとかにはそういうニッチな情報も細切れながらもあるもので、例えばx軸の目盛りを10xの形に表示する(これは割と定番ぽい)場合は、

stackoverflow.com

などがあります。対数軸の場合、1e+02のような表示になりますが、これをscale_x_continuousでも有効にするには(xじゃなくてyでも)

stackoverflow.com

等がありました。

しかし、肩の上にある数字が小さくておじさんには見づらいです。106ならM、109ならGとかにしてほしい…と思ったら

stackoverflow.com

がありました。今回は一番下の、SI接頭辞を使う方法を使うことにしました。評判が悪ければ戻すけど…。sitoolsっていうパッケージがあるんですね。

あなたはパッケージを作成するしかないでしょう。あなたの進む道は用意してあります

Twitterで呟いていたら、Atsushiさんから

と言われてしまったので、パッケージにgeomとthemeを詰めこんで、ggplot2の拡張パッケージの形で作ってみますか…。

実際あれば便利だし、R使用歴的にも良いタイミングかな。

既に結構課題があるので記事にしつつ、作っていくかな…がんばるぞい!

ということで…

Enjoy!!


  1. 縦軸を対数取る場合はあらかじめ20*log10(x)していることが多いので、軸そのものの設定を変更するのはx軸が多い…。

(R) (Julia) JuliaCallパッケージを使用してRmd中からJuliaを実行して結果を表示する (メモ)

PythonInRのノリで使えば良さそう。

追記

実はid:yutannihilationさんが分かりやすい記事を既に書いていたという…(調べなさいよ…)

notchained.hatenablog.com

記事中で指摘されている件は

Fix the bug that julia_setup() fails to correctly load libjulia.dll if JULIA_HOME is not in path on windows.

ということで、最新のバージョンではJULIA_HOMEが設定されていなくても大丈夫(当然Julia見つからないというエラーは出る)でした。

状況的にはこの記事当時とあまり変わっていない気がしますね…。

おまけの本文。

Julia使いやすいけど、やはり開発環境が気になるところです。Junoも凄い使いやすいのですが、やはり使い慣れたRStudio IDE上で実行できると便利だなーと思って、まずはRからJuliaを実行できるようにしたパッケージないかなと探したところ、ありました。その名もJuliaCallパッケージ。

公式のサイトはこちら。
Seamless Integration Between R and 'Julia' • JuliaCall

CRANにもある。
CRAN - Package JuliaCall

結構前からあるから周知だったりしますかね…

Githubはこちら。何か見つけたら報告しましょうか… github.com

インストール

JulliaCallパッケージ自体はinstall.packages("JuliaCall")で良いですが、julia_setup()時にjuliaにPATHが通っていないと「Juliaが見つかりません」というエラーになります。
WIndows環境でJunoを使っている場合など、JuliaへのPATHが通っていないことがあるので要確認&設定です。

初回のこの設定が意外と?時間がかかります。何をしているのかは調べてないので良く分かりませんが…。

Rmd中にjuliaを埋め込む…

まぁ、ビニエット vignette("Julia_in_RMarkdown")を読んでください、でおしまいなのですが、それだとあんまりなので…。

Rmdのyamlヘッダのあと、要するに本文に下記のように書いて実行してみました。なお、バックスラッシュ()で始まっている行のバックスラッシュは削除してください。はてなブログにブロックの終わりと見られてしまうので、苦肉の策。何か良い方法をご存知の方は教えてください…。

\``` {r setup, include=FALSE}
library(JuliaCall)
knitr::opts_chunk$set(echo = TRUE)
knitr::knit_engines$set(julia = JuliaCall::eng_juliacall)
\```

# Julia Test

\```{julia}
# julia のチャンクの中ではjuliaのルールで実行される。
# julia はコードを実行すると結果を表示するので、下記の代入操作だけでaの値が表示される。
a = sqrt(2)
\```

\```{r}
# r のチャンクの中ではrのルールで実行される。
# 通常の代入では結果は表示されない。()で全体を囲うことで表示させられるが。
a <- sqrt(2)
# 改めて、aの値を表示するためにaと打ち込む。
a
\```

##  doc test

\```{julia}
# juliaのチャンクの中でsqrtについてヘルプを読む。
@doc sqrt
\```

## eval from R chunk

\```{r}
# RからJuliaの変数にアクセス
julia_eval("a")
\```

ということで、ひとまずRからJuliaに処理を渡したり、Rmd中にjuliaのコードを書いて平然と表示させることが出来ることは分かりました。
しかし、Rは型についてはかなり緩い一方でJuliaは型のチェックが厳しいので、その辺りの仕様をちゃんと把握しないと実用上はトラブりそうですね。

Juliaのパッケージを使用することも出来るらしいので、RとJuliaの得意な部分で住み分けて使えれば…かなり良さを感じます。 ただ、Junoで使えたようなJuliaのための入力補完や\で始まる文字、例えば≈の入力はキツイですね。Juliaのコードを外部に保存してchunkで読み込めば良い気がするのでいずれやってみましょうか…。

上記のコードの実行結果は以下のようになります(タイトルとかyamlヘッダ中のコードはここには書いていませんが…)

f:id:niszet:20180324181744p:plain

(だれか細かいところ説明してくれないかなー…)

Enjoy!!

(Julia) 春の Julia 10k stars 祭り 1 of 2 に参加してきました

平日開催の勉強会の参加は多分初めて。

そんなわけで参加してきました。 data-refinement.connpass.com

Julia Boxのチュートリアルをysaito8015さんが翻訳していて、それを見ながらコードを実行して試していくというスタイルでした。

私はJulia Boxの調子が良くなくて、手元のJuno(Atom上でのJulia実行環境)にて実行していたのですが。

4章まで進めた。

ループの書き方まで少し出来るようになりました。チュートリアル的なものは以前もやっていたのですが、改めてまだまだ知らないことがあるナ…と。

niszet.hatenablog.com

一か月前か…ようやく進捗出た感じ。

型を指定した辞書

昨日あった話で、Dictを最初に作成するときに、キーと値それぞれの型が確定して、以降はその型にあったキーや値でないとエラーになってしまいますよね。

myphonebook = Dict("Jenny" => "867-5309", "Ghostbusters" => "555-2368")


#> Dict String → String with 2 entries
#> "Jenny" → "867-5309"
#> "Ghostbusters" → "555-2368"

が、これを最初に空の状態で作ってしまいたい。で、思ったのが

myphonebook = Dict(String => String)

なのですが、これは

#> Dict DataType → DataType with 1 entries
#> String → String

となってしまってString -> String にならないのです。型を指定するなら、

myphonebook = Dict{String, String}()

#> Dict String → String with 0 entries

とするのが正しいのでした。左後ろの方に教えていただいたです。コンストラクタと型の指定周りがまだ私はわかってないぽいですね。

後半には線形代数の問題とかがあるということで、Juliaの力を見るにはそこまで進めていかないとな~…と。少しずつやっていこうと思います💪

(R) fsパッケージでfile_moveを使うときに、ディレクトリを変更するような場合はファイル名もつけておかないといけない (メモ)

1.0.0のときは大丈夫だったんだけど…

fsパッケージでカレントディレクトリにある、bbbってファイルをtestってディレクトリに移動させたい場合、

fs::file_move("bbb", "test/bbb")

としないといけないようです。 もし、

fs::file_move("bbb", "test/")

としてしまうと、test/test として移動してしまう。これはfsのCRAN上にあるバージョン1.2.1で確認した挙動です。1.0.0のときは後者でも大丈夫だった。

コレが仕様なのかバグなのかは履歴等追って、場合によってはissueかなぁ…(英語苦手よ…)

とりあえず確認出来たことだけ1

Enjoy!!


  1. fsパッケージについてはきっとどなたかがまとめてくれるはず…