niszetの日記

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

(R) lobstrパッケージ (メモ)

カラフルなastが作れる…

なんかbuild failingってなっているのが気になりますけど…。あと、pop upする関数ヘルプが軒並みエラーになるのですが…

r-lib漁るシリーズ。

例によってCRANにはない。GitHub版はこちら。 github.com

パッケージに含まれる関数は以下の通り。ヘルプが整備されていないっぽい

ls("package:lobstr")
#> [1] "ast"           "obj_address"   "obj_addresses" "obj_refs"      "obj_size"   

ast()pryr::ast()のカラーになった版のようで、obj_addresspryr::address()と一致を確認しています。obj_size()pryr::object_size()よりも小さい桁まで表示するものの同じものかなと思います。

とはいえ、これ以上の情報がない…。

ast使いに朗報かなと思ったのですが…もうちょっと更新入ったらまた書くかも。

Enjoy!!

(R) sessioninfoパッケージ (メモ) (2019/Jul/17 更新)

CRANには1.1.1が最新として登録されています。

昔のRの記事が当時の情報のまま残っているので、手が付けられるものは加筆訂正していく流れです。

さて、sessioninfoパッケージは本記事執筆当時はCRANに登録されていませんでしたが、その後登録され(更新はされていませんが)現在もCRANからインストール可能です。

install.packages("sessioninfo")

また、下記のUsageで十分使い方はわかるかなと思います。使い方としては記事作成当時と変わっていません。ただし、表示される文字列が多少変化しています。

www.r-pkg.org

私の今の環境で出力するとこんな感じです。

> library(sessioninfo)

> os_name()
[1] "Windows 10 x64"

> platform_info()
 setting  value                       
 version  R version 4.0.2 (2020-06-22)
 os       Windows 10 x64              
 system   x86_64, mingw32             
 ui       RStudio                     
 language (EN)                        
 collate  Japanese_Japan.932          
 ctype    Japanese_Japan.932          
 tz       Asia/Tokyo                  
 date     2020-07-17    

> package_info()
 package     * version date       lib source        
 assertthat    0.2.1   2019-03-21 [1] CRAN (R 4.0.0)
 cli           2.0.2   2020-02-28 [1] CRAN (R 4.0.0)
 crayon        1.3.4   2017-09-16 [1] CRAN (R 4.0.0)
 fansi         0.4.1   2020-01-08 [1] CRAN (R 4.0.0)
 generics      0.0.2   2018-11-29 [1] CRAN (R 4.0.0)
 glue          1.4.1   2020-05-13 [1] CRAN (R 4.0.0)
 packrat       0.5.0   2018-11-14 [1] CRAN (R 4.0.2)
 rstudioapi    0.11    2020-02-07 [1] CRAN (R 4.0.0)
 sessioninfo * 1.1.1   2018-11-05 [1] CRAN (R 4.0.0)
 withr         2.2.0   2020-04-20 [1] CRAN (R 4.0.0)
 yaml          2.2.1   2020-02-01 [1] CRAN (R 4.0.0)

[1] C:/Users/niszet/Documents/R/win-library/4.0
[2] C:/Program Files/R/R-4.0.2/library

> session_info()
- Session info --------------------------------------------------
 setting  value                       
 version  R version 4.0.2 (2020-06-22)
 os       Windows 10 x64              
 system   x86_64, mingw32             
 ui       RStudio                     
 language (EN)                        
 collate  Japanese_Japan.932          
 ctype    Japanese_Japan.932          
 tz       Asia/Tokyo                  
 date     2020-07-17                  

- Packages ------------------------------------------------------
 package     * version date       lib source        
 assertthat    0.2.1   2019-03-21 [1] CRAN (R 4.0.0)
 cli           2.0.2   2020-02-28 [1] CRAN (R 4.0.0)
 crayon        1.3.4   2017-09-16 [1] CRAN (R 4.0.0)
 fansi         0.4.1   2020-01-08 [1] CRAN (R 4.0.0)
 generics      0.0.2   2018-11-29 [1] CRAN (R 4.0.0)
 glue          1.4.1   2020-05-13 [1] CRAN (R 4.0.0)
 packrat       0.5.0   2018-11-14 [1] CRAN (R 4.0.2)
 rstudioapi    0.11    2020-02-07 [1] CRAN (R 4.0.0)
 sessioninfo * 1.1.1   2018-11-05 [1] CRAN (R 4.0.0)
 withr         2.2.0   2020-04-20 [1] CRAN (R 4.0.0)
 yaml          2.2.1   2020-02-01 [1] CRAN (R 4.0.0)

[1] C:/Users/niszet/Documents/R/win-library/4.0
[2] C:/Program Files/R/R-4.0.2/library

再現可能性を高めるために、当時のバージョン情報を残すという点では、通常はsession_info()で出力すれば十分でしょう。ただし、Rの外にある環境、たとえばPythonのコードを使っているとか、Pandocの特定のバージョンを使っているだとか、は、別途意識して残さないといけませんが…。RMarkdownでレポートを作成する際に、これらの情報を入れられると良いと思います。


以下は記事作成当時の古い情報を含んでいます。記録のため残しておきます。

最近は更新されていないし、CRANにもいませんが…

r-lib漁ってて見つけたので。

github.com

通常のsessioninfo()関数。

sessionInfo()
#> R version 3.4.3 (2017-11-30)
#> Platform: x86_64-w64-mingw32/x64 (64-bit)
#> Running under: Windows >= 8 x64 (build 9200)
#> 
#> Matrix products: default
#> 
#> locale:
#> [1] LC_COLLATE=Japanese_Japan.932  LC_CTYPE=Japanese_Japan.932   
#> [3] LC_MONETARY=Japanese_Japan.932 LC_NUMERIC=C                  
#> [5] LC_TIME=Japanese_Japan.932    
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> loaded via a namespace (and not attached):
#> [1] compiler_3.4.3 tools_3.4.3    yaml_2.1.16   

sessioninfoパッケージの方は、いくつかの関数に分かれています。

sessioninfo::os_name()
#> [1] "Windows >= 8 x64"
sessioninfo::platform_info()
#>  setting  value                       
#>  version  R version 3.4.3 (2017-11-30)
#>  os       Windows >= 8 x64            
#>  system   x86_64, mingw32             
#>  ui       RStudio                     
#>  language (EN)                        
#>  collate  Japanese_Japan.932          
#>  tz       Asia/Tokyo                  
#>  date     2018-03-05             
sessioninfo::package_info()
#>  package     * version    date       source                            
#>  clisymbols    1.2.0      2017-05-21 CRAN (R 3.4.2)                    
#>  sessioninfo   1.0.1.9000 2018-03-03 Github (r-lib/sessioninfo@c871d01)
#>  withr         2.1.1      2017-12-19 CRAN (R 3.4.3)                    
#>  yaml          2.1.16     2017-12-12 CRAN (R 3.4.3)                    
sessioninfo::session_info()
#> ─ Session info ────────────────────────────────────────────────────────────────
#>  setting  value                       
#>  version  R version 3.4.3 (2017-11-30)
#>  os       Windows >= 8 x64            
#>  system   x86_64, mingw32             
#>  ui       RStudio                     
#>  language (EN)                        
#>  collate  Japanese_Japan.932          
#>  tz       Asia/Tokyo                  
#>  date     2018-03-05                  
#> 
#> ─ Packages ────────────────────────────────────────────────────────────────────
#>  package     * version    date       source                            
#>  clisymbols    1.2.0      2017-05-21 CRAN (R 3.4.2)                    
#>  sessioninfo   1.0.1.9000 2018-03-03 Github (r-lib/sessioninfo@c871d01)
#>  withr         2.1.1      2017-12-19 CRAN (R 3.4.3)                    
#>  yaml          2.1.16     2017-12-12 CRAN (R 3.4.3)                    

それぞれの表示はこんな感じ。

何がうれしいのか

ちょっとだけ表示は見やすくなっていますね。ただ、返ってくる値はlistになっているので扱いやすくなったかは、どうだろう…?

いずれにしてもまだCRANには置いてなく、開発もそれほど活発にはされていないので重要度は低いのかなぁという感じ。どうなんでしょう??

今回はここまで。

Enjoy!!

(R) RStudio IDE 上の View() がどこから来ているか調べる (1回目) あるいは RStudio IDEによって置き換えられた関数の一覧など

調べられるところまでは頑張る。

さて、View()で色々見れますよ~という話をしてきましたが、結局このView()はRStudio IDEによって上書きされた関数ということでした(オリジナルはutilsにいる)
さて、こうなってくるとこの関数が一体どこで作られて出てきているのか気になります。ということで調べられるだけ調べていきます。

が、この話は長くなりそうなので何回かに分けて書いていきます。

RStudio IDE上で置き換えられている関数の一覧

現時点で把握している、RStudio IDE上で置き換えられている関数の一覧は下記のとおりです。おそらくこれで全部。 なお、これはGitHub版のソースから判断しています。バイナリ版は少し違います(後述)

grDevices::quartz
utils::history 
utils::loadhistory
utils::savehistory
utils::timestamp
utils::file.edit
utils::View
utils::edit
utils::install.packages
utils::remove.packages

結構あるような、そうでもないような。RStuio IDEのPaneとかに表示されるようなものはまぁ大体上書きされているということですね(考えてみれば当たり前か)

バイナリ版はこれら関数のうちedit()はオリジナルのままです。他は上書きされていることをコンソール上で実行して確認しました。
ということは、次のバージョンあたりで挙動が変わるということですね。

また、grDevices::quartzは使用できないようにしているようです。古いバージョンのRに含まれるのでしょうか、ソースを確認すると、

.rs.addFunction( "disableQuartz", function()
{
  .rs.registerReplaceHook("quartz", "grDevices", function(...) {
    stop(paste("RStudio does not support the quartz device in R <= 2.11.1.",
               "Please upgrade to a newer version of R to use quartz."))
  })
})

ということが書かれています。

なお、View()は下記のリンクの先にある。更新とともにずれていきそうだが…。

github.com

.rs.registerReplaceHook("View", "utils", .rs.viewHook)

Viewはどこにいるのか。

ソースコード上の所在は上に書いた通りです。では実際に実行時にはどこにいるのでしょうか?パッケージ?グローバル環境??

実際にコンソール上で関数名だけで呼べば、environmentが表示されるのでどこにいるのかわかります。

View
#> function (...) 
#> .rs.callAs(name, hook, original, ...)
#> <environment: 0x000000000c62fc40>

…となりますが、environmentはnew.env()で与えられたような値ですね。

親環境を追う

ということでこんどはこの親環境を追っていきます。親環境についてはrlang::env_parents()で見ていくことが出来ます。
この結果はlistで返ってくるので、例によってView()で表示させるとこんな感じになります。

View(rlang::env_parents(environment(View)))

f:id:niszet:20180305224720p:plain

このとき、View()の親の親環境についてAttributesを表示させて該当する行を選択する形で生成された、下のコードを実行して結果を見てみると…

attributes(rlang::env_parents(environment(View))[[2]])[["name"]]
#> [1] "tools:rstudio"

となります。検索するとView()の中にあった.rs.callAs()もここにいることがわかります。RStudioがなんらかの方法で差し込んだ環境であろうといことがわかりますね。

そして、View()自身の環境を見てみると、

View(environment(View))

f:id:niszet:20180305225058p:plain

この環境にはoriginalという変数があり、これは

identical(utils::View, environment(View)[["original"]])
#> [1] TRUE

という結果になるように、本当にオリジナルであるutils::View()であることがわかります。

なんだか少しずつ見えてきました。というか、ソースコード読んだのでもう大体対応関係分かりますよね。OSSのメリットですね。

そんなわけでもう少し見ていきます。長くなってきたので複数回に分けてみます。

Enjoy!!

(R) そろそろCSSでスライドの見栄えをいじれるようにしようか… (1回目)

これはRカテゴリではないような気もする。

さて、先日のTokyoR 68のLTでちょっと1課題が…。 niszet.hatenablog.com

通常の設定でのrevealjsでのスライドではコードのサイズが非常に小さく表示されてしまい、スライドの表示が小さいときには文字が見えないという問題があります。
y__mattuさんからCSSの修正をすると良いですよ、ということで教えていただきました。

そもそも、スライドに変換したときにはどんな感じに出力されているの??

さて、今回はcssをいじって文字サイズをちょっと大きくして対応できました。
しかし、次につなげるためには生成されているスライドの中身をみて、自分でも解決できるようにしておきたいところです。生成されるスライドはhtmlになっているので、html+cssの知識がと気合があれば読み解くことはできます(たぶん)

幸いなことにインターネット老人会所属のniszetさんは手でhtmlを書いてホームページ2を公開するという黒歴史をちゃんと持っています。そのため、htmlとcssについての基本的なことはなんとなく知っています。ただしhtml5などの新しい技術についてはついていけていません。老人会所属なんで。
ということで、そちらも調べつつ少しずつ見ていくことにします。

問題のコード部分

インラインに"`"を使って書いた場合、htmlになったときは

<code>head()</code>

のようにcodeタグで囲まれるようですね。

"```" で囲まれた場合はこんな感じでpreとcodeで囲まれるようだ。

<pre><code>g_gpoint_iris &lt;- ggplot() + geom_point(data = iris, 
             mapping = aes(x = Sepal.Length, y = Sepal.Width))
g_gpoint_iris</code></pre>

Rのコードの出力結果も同様で、preとcodeに囲まれている。

<pre><code>## List of 3
##  $ a: int [1:3] 1 2 3
##  $ b: raw 02
##  $ d: cplx 1+3i</code></pre>

さて、問題のコード部分ですが、各ブロックを改行して展開するとこんな感じ。全体をdivで囲ってpreとcodeで囲い、aでも囲う。関数名とか演算子、変数数字などは個別にclassをもったspanで囲われて、()などは囲われていないですね。3i)が囲われていないのは気になるけど。complexをちゃんと認識してくれていないのかな。

<div class="sourceCode" id="cb1">
<pre class="sourceCode r">
<code class="sourceCode r">
<a class="sourceLine" id="cb1-1" data-line-number="1">
<span class="kw">list</span>
(
<span class="dt">a=</span>
<span class="dv">1</span>
<span class="op">:</span>
<span class="dv">3</span>, 
<span class="dt">b=</span>
<span class="kw">as.raw</span>
(
<span class="dv">2</span>
), 
<span class="dt">d=</span>
<span class="dv">1</span>
<span class="op">+</span>
3i) 
<span class="op">%&gt;%</span>
<span class="st"> </span>
<span class="kw">str</span>
() -&gt;
<span class="st"> </span>
res</a>
</code></pre></div>

ということで、これらについて個別にスタイルを定義すれば見栄えを変えられそうです。
今のtheme(Blood)だとコードの文字色が見づらいのでこれは変えたい。あと、コードの前後に余白が多いのはdivが悪さをしているのかな?という気がしますね。

まずはcssで各タグについての設定、あとclass毎の設定方法を調べて変更してみれば良さそうですね。

見栄えの調べ方

Google Chromeを使っている場合、その他のツール -> デベロッパーツール でhtmlの各要素が表示上のどこの部分と対応しているのかがわかりやすく表示されます。

結果として、margin要素を削ればコードが詰めて入りそうです。 y_mattuさんに教えていただいた設定を、自分のスライドに合わせたサイズ感にして、divとpreのmarginを削った形で、下記のような設定を足してみました。

.reveal pre {
  margin-top: 10px;
  margin-bottom: 10px;
}

.reveal pre code {
  font-size: 1.3em;
  line-height: 0.85;
}

div.sourceCode { 
  /*display: inline-block;*/
  margin: 0;
}

さて、比較してみるですよ。まずはオリジナル

f:id:niszet:20180304204927p:plain

こっちが修正版。オリジナル版よりコードの文字ちょっと小さくしてしまってます。

f:id:niszet:20180304204943p:plain

これでコードが詰まったので文字サイズの調整にもう少し余裕がとれそうですね。 不定期にもうしばらく続けてみます。

Enjoy!!


  1. ちょっと…?

  2. 歴史の闇に葬られましたよ

(R) ggplot2の gg, ggplot オブジェクトに格納されているlayersは名前を持っていてほしい

昨日のTokyoRの一次会でちょっと話したやつ

View()で見ていくとき、layersに入っているレイヤーオブジェクトには名前がなく、[[1]]とか[[2]]とかそっけない。そして複数のレイヤーを重ねた場合にはどれがどれかわからん…!となりそう。
じゃあレイヤーに名前つけてみるかぁという気持ちをRで書くとこんな感じかな。

# データの準備。これは例のkazutanさんの記事からの引用。
library(ggplot2)
g_null <- ggplot()
geom_point_iris <- geom_point(data = iris, mapping = aes(x = Sepal.Length, y = Sepal.Width),
                              stat = "identity", position = "identity")
g_gpoint_iris <- g_null + geom_point_iris
# 準備はここまで

# 名前を付けるのはここ。レイヤー枚数に応じて代入する文字を適当に追加してあげてください。
names(g_gpoint_iris$layers)<-c("Scatter_Plot")
View(g_gpoint_iris)

f:id:niszet:20180304201804p:plain

これでgeom_point()で追加されたlayerは"Scatter_Plot"1という名前を持ちます。コンソール上にg_gpoint_irisと書けばちゃんとプロットもされますね。
f:id:niszet:20180304202005p:plain

おまけ

まぁこれだけで終わるのもなんなので、zeallotを使ってlayer取り出そうと思ってやってみたコードがこちらです。

library(ggplot2)
library(zeallot)
library(magrittr)

# %->% の list 対応
destructure.list <- function(x){x}

# 以下はggplot側のデータの作成(さっきのと同じ)
g_null <- ggplot()
geom_point_iris <- geom_point(data = iris, mapping = aes(x = Sepal.Length, y = Sepal.Width), stat = "identity", position = "identity")
g_gpoint_iris <- g_null + geom_point_iris
# View(g_gpoint_iris)

# classをいったん消してlistにするので復元するためにclassの値を保存しておく
class_name <- class(g_gpoint_iris)
# 同様に、要素の名前も保存しておく
top_hier_names <- names(g_gpoint_iris)

# これを実行すると.GlobalEnvに9つの変数が出てくる…
g_gpoint_iris %>% unclass %->% c(data, layers, scales, mapping, theme, coordinates, facet, plot_env, labels)


# layerに名前を付ける。今回は1つだけ
names(layers)<-c("Scatter_Plot")

# listを再構成
g_gpoint_iris_ln<-list(data, layers, scales, mapping, theme, coordinates, facet, plot_env, labels)

# classを復元
class(g_gpoint_iris_ln) <- class_name

# nameも復元
names(g_gpoint_iris_ln) <- top_hier_names

# みてみる
View(g_gpoint_iris_ln)

f:id:niszet:20180304202516p:plain

と、いう感じ。ちゃんとg_gpoint_iris_lnとコンソールに書いてEnterでplotされますな。

補足

道を踏み外した感じがありますが、ちょっと色々確認したかったので…。

destructure.list <- function(x){x} はコメントにあるように %->% の list 対応。 zeallot%->%を使う場合にはclassに応じた関数を準備しておく必要がある。data.frameは内部でlistにしているだけなので、listなら引数をそのまま返せば良いだろう。
しかし、なぜ素の状態でlistの対応がないのだろう。不思議

実はdestructure.ggだとなんだかうまくいかないのですよね…(理由はよくわかっていない)。そのため、ggのオブジェクトはそのまま渡せず、今回はunclass()でclass属性を消して単なるlistとなっています。で、これをzeallotで分解して各要素に分けています。

その後layersに名前を与え、分解した要素をlistにして再構成して、class()でもともと持っていた"gg"と"ggplot"を与え、listsの要素には元のggクラスだった時の名前を与えなおしています。ggplotのオブジェクトは要素名が上記のようになっていないとプロットしてくれないらしく。namesを与える部分を省略して実行してみてください。View()で中身を見ても良いかも。

これはRStudio上の挙動なのかもしれませんが…。素のRで確認とかはしていないです。
そもそもなぜggのオブジェクトをコンソール上で叩くとプロットされるのかと言えば、実際にはggplot2:::print.ggplot(g_gpoint_iris)が呼び出されているからで2…しかしこれはREPL上の動きなので実際は… yutannihilationさんの記事をご参照ください notchained.hatenablog.com

zeallotを積極的に使っていきたみだけでやってみた感じの記事ですね。

Enjoy!!


  1. ラクダなのか蛇なのかはっきりしろよって感じの名前にしてしまった…。しかしやり直すのが面倒くさいのでこのままにしてしまうのであった。みなさんはちゃんと命名規則を守ろうね!

  2. 記事に書かれているように、REPL上の動きはprintで直接呼んだ時とは挙動が違うらしいんですが、今の私には説明できないです。

(R) TokyoR 68でLTしてきました

終わらなかったけど…

ワタシのスライドはここにあります。
TokyoR 68 LTViewとEnvironment Paneでデータの構造も見てみよう

今回は資料のリンクはなしです。

何故なら公式のATNDに書かれているから。kilometerさん、お疲れ様です。 atnd.org

togetterもkashitanさんがまとめてくださってます。

togetter.com

最後まで喋れませんでしたが、kazutanさんの資料をView()で確認しながら読み進めていく話は下の記事にはいっています。

niszet.hatenablog.com

kazutanさんの記事を読みながら、View()で見た表示のされかたが一致しているかなーって感じで見てもらえれば。手を動かして見てみると納得感が段違いだと思いますので是非是非。

反省…

やはり5分では無理がありましたね。内容的にはこのブログに全部書いてあるのですが、やっぱり通して説明があった方が良いですよねぇ…。blogdown挑戦してgithubか?
応用セッションとかも考えてみるべきなのかもしれませんね。

Hatena Blogはちょこちょこしたものを上げるには良いんですけど、長文だと読みにくい(のは文章の問題では)し、検索もちょっと不向きな感じはあるので、まとまった時点でどこかにまとめなおすと良いのかな。

RStudioの隠された機能はまだまだあるはずなので、どんどん明らかにしていきたいなーって思います。とりあえず全部のボタン押す感じで。

Enjoy!!

(R) File I/Oのパッケージ(その名もio)が作られはじめた (メモ)

4日前から?

ひとりで春のr-lib発掘祭していたら見つけたこのパッケージ。

github.com

まだ出来て間もないのでまだ中身は最小限しかないっぽいですが、file I/Oまわりをすっきりさせようということでしょうか。実装はC++で書くような感じですね(今は大抵そうなのかな)

確かに、Rはcsvなどで書かれたファイルのI/Oはreadrパッケージなどによってかなり高速になってかつ使いやすいものとなっていますが、素のファイルの入出力はまだ伝統的な関数しかないと思います。
ここが整備されると、ガチの前処理(csvなどに整形するところまで)Rでやれることになるのかな…

という期待を込めてWatchとStarしてみました。

Win+日本語とかはきっとハマりどころなので、何か見つけたら報告できるように頑張ろう。

そういえば、例のstylerの日本語含むコードが消えるissue、

github.com

は、

とのことで、更新されたらまた試してみようと思います。

今日はTokyoR 68です。LTしてきます。資料をGitHubにupしたいがやり方をすっかり忘れてあたふたしていたらこんな時間。そろそろ出る準備をしながら…upできるかなぁ…

Enjoy!!