カテゴリー別アーカイブ: プログラミング

RをJavaScript(Node.js)から使ってみる +α:R Advent Calendar 2017 day 7

この記事は、Japan.R 2017での講演内容を再編成した物です。

Node.jsで作られたアプリケーションや、Electronアプリケーションを、Rと連携させたいと思ったことはありませんか?

JavaScriptとRの連携

Rで統計処理をしているときに、JavaScriptでインタラクティブなビジュアライゼーションを行いたい、ということはあると思います。この目的であれば、shiny (Winston Chang et al.)という便利なパッケージがあります。htmlwidgets(JJ Allaire et al.)も便利なパッケージで、threejsbokehなどの連携を行うことができます。

では、逆は、というとあまり決定的なアプリケーションはありません。npmをみてみると、controlr, r-script, computerというパッケージがありますが、どのパッケージもRをspawnしてstdin/stdout経由でアクセスしているだけであり、すこし物足りません。

そこで、勉強がてら自前ですこし作ってみることにしました。

libr-bridge

libr-bridgeはlibr(WindowsではR.dll)と連携して、Node.js環境からRを使用するパッケージです。

let r = new R();

const arrA = [1.00, 3.36, 8.01, 1.22, 3.74, 2.43, 7.95, 8.32, 7.45, 4.36];
const arrB = [1.04, 3.65, 6.82, 1.46, 2.70, 2.49, 7.48, 8.28, 8.93, 5.63];

/* Some functions are already loaded to libr-bridge */
console.log("Mean of arrA: " + r.mean(arrA));
console.log("Mean of arrB: " + r.mean(arrB));
console.log("Peason's correlation coefficient: " + r.cor(arrA, arrB));

libr-bridgeを利用することで、Rの関数にアクセスすることが出来ます。eval関数も備えていますので、とりあえずデータだけ渡してしまって、凝った作業をRスクリプトで行い、結果を受け取ることも出来ます。

まだまだfactorやdata.frame, S3/S4クラスなど対応しないと行けないことは山積みですが、Node.jsで出来る作業の幅を広げてくれます。

どうやって実現しているの?

ぜひ、ソースコードを見ていただきたいですがlibRのAPIをゴリゴリに呼び出して動作を行っています。Rの内部挙動を理解するのにも役に立ちました。

小ネタ

Rでは倍精度浮動小数点(double9は他言語と同じようにIEEE 754に従って、実装されています。これは、1bitの符号と、11bitの指数部、52bitの仮数部で数値を表す方式です。

NaNはこの決まりに含まれており、指数部のbitがすべて1であり、仮数部が0以外のもの、と定められています。これは他の言語も共通です。

しかし、 NAはR独自の表現であり、この決まりの中には含まれていません。

Rでは、少し特殊な仕組みでNAを実現していて、仮数部が1954(R言語設計者の一人のRoss Ihakaの誕生年)のNaNをNAとして区別して扱っています。

今回、libr-bridgeを作るのに、Rの内部を調べていくうちにこういった小ネタをいくつか見つけたので、また次の機会にでも記事にしたいと思います。

Electronドキュメントの翻訳 (Crowdinへの移行) : Electron Advent Calendar 2017 day 4

Electronの多言語ドキュメントが最近Crowdinへ移行し、翻訳作業が大変やりやすくなりました。

ここでは、その経緯と使い方について説明しています。

なぜCrowdinに移行したの?

もともとは日本語など、英語以外のドキュメントもelectronレポジトリの中に含まれており、翻訳を行う際にはdocs-translationsを編集してpull requestを送る、という方法で行われていました。

しかし、この方法には

  1. ドキュメントがなかなか英語の最新版に追いつかない
  2. Pull requestの処理が大変

という問題がありました。

一点目の「ドキュメントがなかなか英語の最新版に追いつかない」ですが、docs(英語版)のドキュメントが編集され、新しいメソッドの追加やメソッド名の変更があったり、書かれていた方法がDeprecatedになっていても、なかなか翻訳版のほうがそれに追いつかなかったり、またたくさんの言語があるために言語ごとにバラバラの作業で一貫性が保てていないという状態になっていました。

二点目の「Pull requestの処理が大変」ですが、electronリポジトリには、たくさんのPull requestが送られていますが、動作に関わるもの多くなかなか大変そうです。それにもかかわらず、細々したドキュメントの翻訳などのmerge作業もCheng ZhaoさんZekeさんをはじめとしたElectronの開発コアメンバーが行うことになってしまっていました。

そこで、翻訳の作業の効率化と質の向上のためCrowdinに移行することになりました。

doc-translationsディレクトリは、Deprecate /docs-translations #11039をもって削除されて空になっています。

Crowdinってなに?

CrowdinはWebから使用できる翻訳プラットフォームです。Githubとの連携がとてもしやすく、またオープンソースソフトウェアの開発には無料で使用できるという大きなメリットがあります。

一度翻訳した言葉をドキュメント内で一貫性を保つためにシソーラスを作ったり、機械翻訳を参考にしたり、複数人での作業のために投票機能があったりと、さまざまな機能があります。

どうやって使うの?

まずはCrowdinのユーザー登録を行います。登録にはGithubやTwitterのアカウントを利用することが出来ます。登録後、Electronドキュメント翻訳のプロジェクトを開きます。

言語の設定を行っているためJapaneseが一番上にあがっています。翻訳を行う言語をクリックします。

クリック後は、ドキュメントに含まれるファイルが出てきます。右の青いバーが翻訳率で、こう見ると日本語はほとんど翻訳されていないファイルも多いのが分かります。

今回は、翻訳が全くされていないinstallation.mdを翻訳することにしてみます。ファイルを開くと下のような画面が表示されます。

左側に翻訳文書全体が表示されます。赤がまだ作業を行っておらず未翻訳の部分、黄色が現在編集中の部分、緑が翻訳済みの部分です。

右側で実際の翻訳作業を行います。場合によっては下の機械翻訳や、過去に翻訳したドキュメントに同じ文章があれば表示されますので、それを参考にします。タグは<0></0>といった形で原文の物を引用できます。

翻訳の都合上、タグの順番が変わったり、括弧の対応が減ったりすると警告が表示されますが、わかりやすい翻訳にするためにあえて文書を構成した場合は気にしなくてかまいません。

翻訳されたドキュメントはどこから見るの?

翻訳されたドキュメントは、Crowdinからしばらくするとelectron-i18nリポジトリに取り込まれ、Electronのウェブサイトから見ることが出来ます。数日以上かかることもあるので気長に待ちましょう。

Pocket C.H.I.P. が届いた

Pocket C.H.I.P.が届きました。2016年5月に申し込みをしているので、実に半年かかったことになります。(当時はまだ49$でした)

プチプチに包まれたPocket C.H.I.P.

こんな感じのプチプチに包まれて香港からやってきました。

C.H.I.P.とPocket C.H.I.P.

Pocket C.H.I.P.にあわせて、C.H.I.P.とHDMI DIPを購入。こちらもおいおい触って行きたいです。 続きを読む

タブ文字はもう使うべきではない (Python + vim編)

Ubuntu 12.04 LTSからUbuntu 14.04 LTSにアップグレードしたところ、vimの設定ファイルが変わったのか、自分の.vimrcの設定に関わらず、tabstopが8で表示されるようになってしまいました。

tab8

続きを読む

LMS法について

近年、年齢ごとの標準値などを考える際に、LMS法という統計手法が用いられることが多くなっています。

従来の正規分布の考えと、その考え方からなぜLMS法が生まれてきたかを解説します。

続きを読む

gitのお気に入りコマンドなど

お気に入りのgitの設定およびコマンドです。

git status -sb

[alias]
st = status -sb

と登録しておくのがお勧めです。git status –short –branchの省略形です。

通常の場合、

$ git status

を実行すると、

gitstatus

と、本来必要である情報以上にたくさんのメッセージが表示されます。もちろん、なれないうちは大変助かるメッセージではありますが、慣れてくると冗長すぎてむしろ見通しの悪さを感じてきます。

$ git status -sb

では、

gitstatussb

と、本来必要な情報を簡潔に表示してくれます。

git 1.8.4以上をお使いならばGitの更新ログにあるようにstatus.shortとstatus.branchというconfigがありますのでそちらを利用するのもお勧めです。

pager = less -r

(参考: どせいけいさんきより)

git diffなどの結果は、core.pagerで設定したコマンドに送られます。現在の設定が不明な場合は

$ git config --get core.pager

で調べることができます。おそらく、設定していない場合はlessが標準のページャとして使用されていると思います。

標準のlessは長い行を折り返してくれないので、

gitless

こんなかんじで、長い文は右側にはみ出してしまって見通しが悪いです。

.gitconfigに

[core]
pager = less -r

と設定することで、

gitlessr

長い行は自動的に折り返してくれるので見通しが良くなります。

git diff –word-diff

長い行も一度に表示できるようになって少し見通しが良くなったとはいえ、上記のdiffでは結局どこが変わったのか調べるのはかなり大変です。

$ git diff --word-diff

を使うと

gitworddiff

変更になった部分だけをハイライトして表示してくれます。知っていると便利なコマンドです。

git commit -v

コミットログの記載画面にコミット内容を表示することができます。

gitcommitv

こんな感じでコミットログ記載部分の下部に今回のコミットではどの部分が変更されたかが表示されます。

git log –graph

僕のおすすめは

$ git log --graph --date=short --pretty=format:'%Cgreen%h %cd %Cblue%cn %Creset%s'

です。

gitloggraph

こんなかんじで履歴をコンソール上でグラフィカルに表示してくれます。いろいろ設定オプションがありますが僕は上記を使っています。

もちろん、vim上でgregsexton/gitvを使うという手もあります。

Google Code Jam Round 1A – Problem A. Bullseye

Problem A. Bullseye

X個目(0 origin)の黒い円の半径 = (r+ 2X + 1)2 – (r+2X)2

a2-b2=(a+b)(a-b)なので上記 = (2r + 4X + 1)

n番目までの円を書くと、使うインクの総量はΣ(x=0 to n) 2r+4x+1

Σ(x=0 to n) x= n(n+1)/2、Σ(x=0 to n) 1=n+1。

ので、上記 = 2n2 + (2r+3)n+(2r+1)となる。

2n2 + (2r+3)n+(2r+1) > t →  2n2 + (2r+3)n+(2r+1) – t > 0

解の公式より上記nを求める

結局perlでやってみた。

use bignum;
my $case = <>;

for(my $i=0; $i<$case; $i++){
  my @line = split(/ /, <>);
  my $r = $line[0];
  my $t = $line[1];
  my $circles = 0;

  my $n = (sqrt((2*$r+3)**2 - 8 * (2*$r+1-$t))-2*$r-3)/4;
  $circles = int($n) + 1;   # 0 origin

  print("Case #" . ($i+1) . ": " . $circles . "\n");
}

vim QuickRunとsyntasticで clang++のC++11を使う方法

これでMac OS 10.8.3 Mountain Lion + Xcode 4.6.1でもC++11使い放題。

動かない場合はきちんとclang++がインストールされているか、まずはwhich clang++で確認を。

if executable("clang++")
  let g:syntastic_cpp_compiler = 'clang++'
  let g:syntastic_cpp_compiler_options = '--std=c++11 --stdlib=libc++'
  let g:quickrun_config = {}
  let g:quickrun_config['cpp/clang++11'] = {
      \ 'cmdopt': '--std=c++11 --stdlib=libc++',
      \ 'type': 'cpp/clang++'
    \ }
  let g:quickrun_config['cpp'] = {'type': 'cpp/clang++11'}
endif

 

Git:圧縮とリポジトリのサイズ

Git便利ですね。Gitではオブジェクト(ファイルなど)をzlibで圧縮して保持します。それだけではなく、差分を計算したり、複数のオブジェクトを packすることで、単純にすべての履歴を記録するよりも効率的にリポジトリを保持することができます。

% git --version
git version 1.7.9.2
% alias | grep dirsizeinbyte
dirsizeinbyte='find . -type f -print -exec wc -c {} \; | awk '\''{ sum += $1; }; END { print sum }'\'

duだとファイルサイズではなくてブロックサイズになるので上記コマンドを使います。Landscape – エンジニアのメモを参考にしました。

まずはgit initしただけの状態で。

% git init
Initialized empty Git repository in /Users/kcrt/repostest/.git/
% cd .git
% dirsizeinbyte
13917

13.6KiBです。ここからどうなっていくかを見て行きましょう。まずはテキストファイルから。

% cd ..
% perl -e 'for(1..1000000){print "This is a large text file\n";}' > textfile
% wc -c textfile
26000000 textfile
% git add textfile
% git commit -m "textfile"
[master (root-commit) f274f23] textfile
1 file changed, 1000000 insertions(+)
create mode 100644 textfile
% cd .git
% dirsizeinbyte
165888

Gitはファイルをテキストファイルとして認識してくれました。巨大なテキストファイル(24.8MiB)を追加したにもかかわらず、リポジトリのサイズは162KiBに収まっています。これは繰り返し文字列でありzlibによる圧縮が良好に効いていることによります。

ファイルの一部(10000行目のみ)改変してみましょう。

% cd .. 
% vi textfile
(10000行目のみ改変)
% cat textfile | grep test 
10000:This is a large test file
% git add textfile 
% git commit -m "text->test" 
[master a87fd52] text->test
 1 file changed, 1 insertion(+), 1 deletion(-)
% cd .git 
% dirsizeinbyte 
317734

Gitは一行のみの変化であることをきちんと認識してくれました。しかし、リポジトリのサイズは310KiBとなっています。先ほどのリポジトリのサイズが162KiBなのでほとんど倍です。圧縮されて効率的なのは確かですが、ちょっと期待していた動作と違います。1行だけの変更なので、もう少し小さなサイズになることを期待していました。

Gitは、コンテンツの変更の際も単純にリポジトリに新しいオブジェクトとして追加します。これは高速に動作しますが、ディスク容量の観点からは非効率です。差分を探して、不必要なオブジェクトを削除するにはgit gcコマンドを使います。

% git gc 
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), done.
Total 6 (delta 1), reused 0 (delta 0)
% cd .git 
% dirsizeinbyte 
79679

リポジトリのサイズは78KiBと十分に小さくなりました。一つ目のファイルを追加した際のサイズより小さくなっています。

git gcコマンドは上記のように手動で実行することもできますが、必要と考えられるときやリモートリポジトリへのpushを行う時には自動で実行されます。

それではバイナリファイルの実験に入りましょう。リポジトリを初期化して開始します。

% yes | \rm -R .git 
% git init 
Initialized empty Git repository in /Users/kcrt/repostest/.git/
% perl -e 'for(1..1000000){print "\x00\x01\x02\x03\x04\x05\x06\xfd\xfe\xff";}' > binfile 
% wc -c binfile 
 10000000 binfile
% git add binfile 
% git commit -m "binfile" 
[master (root-commit) 8580c04] binfile
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 binfile
% cd .git 
% dirsizeinbyte 
67942

Gitはファイルをバイナリ(binfile)として認識してくれました。binfileは9.5MiBと大きなファイルですが、繰り返しが多いのでzlibによる圧縮が効率的に行えそうです。リポジトリのファイルは66KiBと期待通り小さなものになりました。

一部を改変するとどうなるでしょうか。

% ..
% vi -b binfile
(:%! xxd 編集 :%! xxd -r)
% git add binfile                                                                   
% git commit -m "small change"                                                      
[master c05696a] small change
 1 file changed, 0 insertions(+), 0 deletions(-)
% cd .git                                                                           
% dirsizeinbyte                                                                     
121847
% git gc                                                                            
Counting objects: 6, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), done.
Total 6 (delta 1), reused 0 (delta 0)
% dirsizeinbyte                                                                     
36149

binfileに16バイトのわずかな変更を加えました。git gcを行うとリポジトリのサイズは35KiBとなりました。バイナリファイルでも差分による圧縮とzlib圧縮を行なって効率的にリポジトリにファイルが格納されることがわかりました。

IS01で右サイドバーの無いアプリを作成する方法

発売して結構時間がたってるけど誰も書かないので書いちゃう。

IS01はよくあるAndroid端末と違い、特殊な解像度を持っています。一般のソフトウェアに配慮してか、右側にサイドバーが表示されてその全体を使うことは通常できませんでした。

今回のサンプルではそれを回避する方法を書いています。

package com.example.is01.fullscreen;
/*
 * IS01 FullScreen Window Sample
 *      IS01の邪魔なサイドバーを回避するサンプル
 *      Programmed by kcrt <kcrt _atmark_ kcrt.net>
 *          Nanoseconds Hunter "http://www.kcrt.net/"
 * $id:$
 */
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import java.lang.Class;
import java.lang.reflect.Method;

public class StartupActivity extends Activity {
    /** Called when the activity is first created. */
    Method setFullScreenMode;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        try{
            Class<?> sgManager = Class.forName("jp.co.sharp.android.softguide.SoftGuideManager");
            Class<?> paramstype[] = {boolean.class};
            setFullScreenMode = sgManager.getMethod("setFullScreenMode", paramstype);
        }catch(Exception o){
            Log.d("is01fullscreen", "failed" + o.getMessage() + ":" + o.getClass().toString());
        }
    }

    @Override
    public void onResume(){
        super.onResume();
        try{
            setFullScreenMode.invoke(null, true);
        }catch(Exception o){
            Log.d("is01fullscreen", "failed");
        }
    }
}

結論からいうと、jp.co.sharp.android.softguide.SoftGuideManager::setFullScreenMode(true)をonResumeで呼び出してあげる事になります。これタイマーで呼び出したりできないのかな。また試してみよう。

Javaでプログラムを書くのは初めてなのでおかしかったらごめんなさいな。

あ、あとバージョンアップで潰されたらごめんなさい。

zipで欲しい人: IS01FullScreenSample