Sumallyのconsole.logが可愛くあざとい件

普段の癖でSumallyを開いた時にWeb Inspectorを立ち上げるとconsole.logにメッセージがあることに気がついた。 なんだこれww

f:id:muddydixon:20131205133836p:plain

「We need couple of talented geeks. Are you the one? Check this out」

f:id:muddydixon:20131205133839p:plain

「探しものはなんですか?見つけにくいものですか?HTMLの中も、JSの中も、探したけれど見つからないのにまだまだ探す気ですか?それより僕と働きませんか?」

f:id:muddydixon:20131205133841p:plain

「コードやHTTPの通信を見て、まだまだ改善の余地あるな、と思ったあなた!僕らのチームに参加しませんか?」

f:id:muddydixon:20131205133843p:plain

「おおっと!Web Inspectorでチェックですか!そういう精神好きです。僕らのチームに参加しませんか?」

f:id:muddydixon:20131205133845p:plain

「We want you for our engineering team. Check this out」

うまいけど僕はそこで上記の画像を回収してそっとWeb Inspectorを閉じました。 閉じました。

GOLDEN BEST

GOLDEN BEST

D3を書くときの小さいTips

marginの扱いがダルい

div > svg > g としてその中にいろいろ追加していく、というのがベストだと思っていますが、marginの取り扱いが割とだるい。よくあるのが

d3.select('div').appned('svg')
  .attr('width', width + margin * 2)
  .attr('height', height + margin * 2)
  .append('g')
    .attr('width', width).attr('height', height)
    .attr('transform', 'translate('+margin+','+margin+')')

とかだと思うけど、この時点で割とイライラしているのでMargin作った

class Margin
    constructor: (args...)->
      @top = 0
      @right = 0
      @bottom = 0
      @right = 0
      @width = 0
      @height = 0

      if args.length is 1
        @top = @right = @bottom = @left = args[0]
      else if args.length is 2
        @top = @bottom = args[0]
        @right = @left = args[1]
      else if args.length is 3
        @top = args[0]
        @bottom = args[2]
        @right = @left = args[1]
      else if args.length is 4
        [@top, @right, @bottom, @left] = args

      @width = @right + @left
      @height = @top + @bottom
    toString: ()->
      return [@top, @right, @bottom, @left].map((d)-> "#{d}px").join(" ")

これを使うとCSSと同じようにmarginを指定できます。

var margin = new Margin(100, 50, 30);  // 上100、下30、左右50
d3.select('div').appned('svg')
  .attr('width', width + margin.width)
  .attr('height', height + margin.height)
  .append('g')
    .attr('width', width).attr('height', height)
    .attr('transform', 'translate('+margin.left+','+margin.top+')');

attrを無限に書くのがダルい

よくあるのが

circle = svg.append('circle')
  .attr('cx', 10)
  .attr('cy', 10)
  .attr('r', 5)
  .attr('fill', 'grey')
  .attr('stroke', 'blue')
  .attr('stroke-width', 3);

これにstyleも同じようにするのがうんざりする

なので、attrsを作った

attrs = (obj)->
  ()->
    for k, v of obj
      this.attr(k, v)
    this

これを使うと

circle = svg.append('circle').call(attrs({
  cx: 10,
  cy: 10,
  r: 5,
  fill: 'grey',
  stroke: 'blue',
  'stroke-width': 3
}))

オブジェクトで定義できるので楽です。(.attr()って無限に書かなくても済むし、なにより、この設定を変数化してもっておける!わーい

可視化における代数処理

このポストは「The grammar of graphics」の5章「代数(algebra)」を(つまみつつ)訳したものです。

5. 代数

代数(algebra)という言葉はアラビア語の「al-jebr」という単語が語源であり、「修復」または「破損した部品の再結合」を意味しています。本章ではグラフに埋め込まれるフレームに対する仕様(specification)を作成するための変数の組の修復(restore)と平衡(balance)に焦点を当てます。 仕様の最初のパートでは、変数の組に関わる代数表現表現を含んでいます。 統語表現の規則を振り返り、ついで典型的な表現の例を紹介します。

5.1 統語論(Syntax)

5.1.1 記号(Symbols)

企業は代数における操作される対象を表すために用いられます。変数の組における記号は

5.1.2 演算子

5.1.2.1 Cross (*)
5.1.2.2 Nest (/)
5.1.2.3 Blend (+)

先行箇所

2.1.7 代数

代数(algebra)は、1) セット、2) セットへの演算子、3) これらの演算子の組み合わせに対する規則の集合です。 この定義は、実数に対する算術の基礎となっている古典的な代数学に対して、より一般的で限定的・抽象的な講義の代数学を含んでいます。

演算子は変形の概念を一般化したものです。セットXに対する演算子は、X x X x ... X として定義された関数で X を返します。 演算子は、unary または monadic (ともに単項)、binary または diladic、または n-ary です。 代数規則は、演算子の結合の仕方を指定します。 例えば、規則 R演算子 "+" は 「(a, b) |-> a + b」を意味します。

2.1.8 変数 (variables)

変数 X は「f : O -> V」のマッピングであり、次のような3つ組を考えます。 X = [O, V, f]

  • 変域 O はオブジェクトのセット
  • 値域 V は値のセット
  • 関数 f はV に属する要素OをVに関連付ける

f の下で O は、X の値を含みます。 可能な値 x を x ∈ V として示します。オブジェクト o (o ∈ O) の値を X(o) と示します。 V が区間のとき、変数は連続です。V と有限な整数の組が等価の時、変数はカテゴリカルです。

変数は多次元であることもあります。 X は p の1次元変数からなるとき、p次元の変数になります。

2.1.9 変数セット (varset)

X = [V, O~, f]

  • 変域 V は値のセット
  • 値域 O~ はオブジェクトのバッグ(元の重複を許す=>同じデータを含むことが可能)
  • 関数 f はV に属する要素OをVに関連付ける

変数セットにおけるグラフィック代数の演算子の定義を簡潔にするために、変数に対してマッピングを反対にしたものです。 同時に、変数のオブジェクトのセットと変数セットのバッグのセットを入れ替えました。 一度以上オブジェクトに対して値をマッピングすることを可能にするために、値域にバッグを利用しました。

2.1.10 フレーム (frames)

変数セットのp次元ドメインとなるすべての可能な値の範囲にあるタプルのことをframeとします。

YAPC::Asia Tokyo 2013に参加&発表&レポートしてきました

YAPC::Asia Tokyo 2013に参加&発表&レポートしてきました。

登壇者・スタッフ・招待合わせて、1131人もの参加者が集まるPerlの祭典「YAPC」。 去年までは一参加者でしたが、今年は発表する機会もいただけたので、20分ですがトークしてきました。

発表

内容もさることながら、裏で「YAPC::Asia Tokyo 2013 特別座談会」、「Perl入学式 @ YAPC」があり僕も聞きたかった「Perlでレコメンデーション」が会ったりと、聞きに来てくれるひとは少ないんだろうなぁと思っていましたが、なにがどうしたのか思った以上に聞きに来てくださったので嬉しかったです。

内容は、1) 可視化の目的、2) 探索的可視化のためのツール、3) DataCubeというモジュール紹介、という誰得な感じのするものでしたが、響くところには響くと信じています。

ちょっとだけモジュールのことを話すと、これちょっとだけメソッドを生やしただけでほとんど「Data::Nest」のラッパみたいなものです。

むしろ、こっちのほうが使い勝手よくてkeyを指定するとNestしてくれます。

use Data::Nest;

my $data = map { {age => int(random(60)), gender => int(random(2))} } (0..10);
my $nest = new Data::Nest();
my $result = $nest->key("age")->key("gender")->rollup("count", sub { scalar @_; })->entries($data);

# [
#    { key => "1", values => [ {
#        {key => "0", values => [条件に当てはまるHash], sum => 13}
#        {key => "1", values => [条件に当てはまるHash], sum => 11}
#        ..
#    }]
# ]

便利。

レポーター

今年は調子に乗ってレポーターにも参加しました。 最初からレポーターをしてくださっている @hiratara さんがすごくまとめてくださったので、それなりに大変でしたが全然ストレスなく楽しんでレポートできました。

メモや写真は大量にあるもののそれなりの分量に抑えるのが大変でした。 私は次のセッションを担当しました。誤字脱字・内容の過不足・修正等あればいってください。

  • 学術分野におけるPerlの活用例
  • 大規模Perl初心者研修を支える技術
  • SPDY、HTTP/2.0の使い方
  • perl な web application のためのテスト情報
  • はてなのサーバ管理ツールの話
  • Mojoliciousでつくる!Webアプリ入門

二日目に自分の発表があったため一日目に固め打ちをしたせいで、初日の疲労は大きかったですw

セッション

レポートしながら聞いていました。

  • OJTの担当でgitを教えて、Perlを教えて、DBを教えて、WAFなしでLAMPでなにかを作らえる、というのをやることが多いのもあり、DeNAの研修が興味深かったです。
  • まきさんの本当にあったレガシーな話はとても代役とは思えない内容で、身震いしながら聞いていました。
  • monocerosはもう少し見てみる
  • とくひろむさんのHTTP::Body::Builderとyappoさんのやりとりはテンポ良すぎてひどいw

ほかにもたくさん見たいのもあったのですがマルチトラックだと悔しいですね!

YAPC

「お祭り!」を感じさせる仕掛けがいっぱいあって、CROSSをやる上で参考になることがたくさんありました。

f:id:muddydixon:20130920181406j:plain

くしいさん、まきさんが引退するという発表で驚きましたが、きっとまきさんもおっしゃってた「新しい芽」が引き継いでくれると信じています。 くまがいくんとか、くまがいくんとか(若くないけど

おまけ

  • 後輩を連れてこれてよかった。ぼっちじゃなかった!
  • songmuさんとtypesterさんと挨拶出来た!
  • 一日目、あれだけ企画してくださっているのに、お弁当抽選に漏れた結果ぼっち飯になりました。
  • 二日目、YAPCに向かってる駅で下駄が割れました。不吉すぎる・・・

f:id:muddydixon:20130921065955j:plain

  • 家族マイレージを貯めるために子供たちを連れて公園に行って遊ばせている間に雅なPerlを眺めていたらFacebook上で犯罪者扱いされていました。

f:id:muddydixon:20130922101006j:plain

grammar of graphics / three stages of graphics creation

この記事は「grammar of graphics」についての理解のためのメモです。


可視化の作成において3つの段階にフォーカスを当てる。

  1. Specification
  2. Assembly
  3. Display

1. Specification

ユーザのアクションをフォーマルな言語に置き換える作業を指す。 ユーザはこの言語に気づいていないかもしれないが、可視化の要請を理解するための自動化システムのためには必要。仕様を定義する他の方法は、可視化の深い文法について説明することでもある。 絵画とは違い、可視化は高度に組織化され制約されたルールセットを持っている。 もちろん、絵画も独自のルールを持っていて、特に写真やビデオのような実際の絵では。 とはいいつつ、芸術家はこの独自のルールを強調するために規則を曲げる特権を持っている。 特殊効果技師は、日常で観察しているものよりもビデオや仮想場面が真実であるように騙す事もできる。 可視化ではそうは行きません。私達は僅かな規則とツールだけしか持っていない。データを偽造したり、統計的な可視化の目的に違反することなしには、オブジェクトの位置や色(これらはデータの属性を表現している)を替えることはできない。データを正確にかつ適切に表現するために。 つまり、可視化システムの核は仕様に基づかなければならない。

統計的な可視化の仕様は6つの宣言で表現される。

  1. DATA: データセットから変数を取り出すデータ操作のセット
  2. TRANS: 変数の変形 (例: rank)
  3. SCALE: スケール(基準、階級化)の変形 (例: log)
  4. COORD: 座標系 (例: 極座標)
  5. ELEMENT: グラフと装飾的(aesthetic)属性 (例: color)
  6. GUIDE: 1つ以上のガイド (例: 軸、凡例)

本書のグラフの殆どで、明示的な定義を行うために、可視化の構文的仕様を書き加えてある。 この仕様言語の古いバージョンは、単一の代数処理のすべての側面を取り込んである。 注釈は不格好で特異的だ。しかしながら、要素としてこれらを分離した。 これらの要素はデータをオブジェクトと結びつけ、これらのオブジェクトを含むシーンを特定する。

2. Assembly

シーンとその記述は異なっている。シーンを表現するという目的において、正確に描画するために私達はその幾何的な配列・形状(geometry)、レイアウト、装飾を調整する。 統計的な可視化のプログラムは、仕様の要素から実際のシーンと合わせて描画し、モデル化するのと同様に、幾何的なシーンに組み上げられなければならない。 本書では、シーンの組み上げよりお仕様について多くを説明しているが、表層的な特徴と深い構造を混同しないためにも仕様について学ぶ一方で、組み上げについても重要視して考えなければならない。 仕様からシーンをどのように組み上げると、結果的な振る舞いにどのように影響をあたえるか。 シーンは動的にも静的にもなりうるし、外部のデータか独立したデータなのか、装飾可能なのか不変なのかは、私達がどのように組み上げるかに依存している。

3. Display

可視化を知覚するために、グラフは装飾的な属性や表示システム(紙やビデオ、ホログラムなど)を利用して描画されなければならない。 現代のオペレーティングシステムでは、いくつもの描画メソッドを利用することができる。これらはよく定義され抽象的なインターフェイスが好ましい。 プロダクションでの可視化は、基本的な描画能力とは異なった、その領域での要件がある。 動的な可視化や科学的可視化は、対照的に、burushingやdrill-down、zooming、linking、その他のデータと可視化を結びつける操作などが可能な洗練されたデザインが要求される。 Becker and Cleveland (1987)、Cleveland and McGill (1988) 、Cook and Weisberg (1994)、 Swayne et al. (1998) はそれぞれの要件について紹介している。最近では、仮想現実ディスプレイや没入型環境などがタッチや音といった装飾を可能なまでに拡張している。

LLまつりに行ってきました

今年もLLイベント「LLまつり」に行ってきました。

今年はLTもしてきました。CROSSの宣伝をしにいくつもりで「CROSSの話かそれがダメならJavaScriptで時系列解析の話で」と申し込むと、後者になっていました。

という訳で僕自身は「JavaScriptで時系列解析」というか前処理の話をしてきました。

内容としてはこんな感じのライブラリです

  • データ可視化の時に可視化表現ごとにデータ取り出すと結構コストなので、一回取り出したデータをゴネゴネしていろんな切り口やタイムスパンで見たいときに便利なモジュール
  • D3はSVG処理とデータ処理・時間処理を分けたほうがいいと思うので、後者を作りたかった
  • plyrとかdata cubeっぽくなんか作ってみたかった(結果としてはd3のアクセサに少し似た形で作った

今後やることはリファクタとドキュメントです。 あとはもう少し分析系(arとかfftでのスペクトラムとか)とか予測周りとか自分に必要な機能をこつこつ作ることとをしたいと思っています。


覚書(というか印象に残ったこと)

  • Common LispC/C++とLLの間
  • 「神の言語」とか考えなければ結構便利に使える
  • それCommon Lispでできるよ
  • Delphiの歴史は一大叙事詩
  • D言語のキャラはキモい
  • @repeatedly さんの「結構流行ってる」は「D言語界隈では」と解釈する
  • Golangにインタープリター「そんなものはありません」
  • 100枚の資料も10分で終わる
  • 郵便配達→エンジニアとか公務員→エンジニアとかペパボすごい
  • 徹夜でハッカソンしたら朝一からLTがおおうけする
  • 外人は忍者大好き
  • ドラ娘は現地調達できる

上記が本編なのですが、個人的に今回一番心に残ったのは休憩時間話してたすたじおさんの

もりすさんとかかぜぶろさんが障害対応でいろいろやったあとの
サーバに入ってhistoryコマンドで勉強してる

という昔の料理人のような姿勢でした。

僕ももっともっと頑張らねば・・・とおもった次第です。

LLイベントの運営のみな様お疲れ様でした! 懇親会でお話させていただいた皆様ありがとうございました!

advent calendar 24日目 selectAll(), data(), enter(), append()に翻弄されるひとたちに

ようやくボクのクリスマスが終わります。

d3は可愛いんですが「selectAll() -> data() -> enter() -> append()」は経験から学ぶのが最も早い、としか答えられません。 クリスマスプレゼントとして、そんな方々のためにUnderstanding selectAll, data, enter, append sequence in D3.jsというエントリが2012/1に出ております。

理解の一助となればと訳しておきました!これほんとに理解できる記事です!


D3.js始めたばっかりの諸君らが、Webで例を見ながら学習するときに、ぶっちゃけ「selectAll(), data(), enter(), append()」という一連の処理はイミフだと思う。そう、これらの関数は、なにをしてるのかわかりづらい。少なくともこれらの機能を理解するのは簡単じゃないと思う。よくわからない諸君らの一助となればと思い例と説明を上げてみることにする。

これらのメソッドが何をしているかを理解するための鍵は、 http://mbostock.github.com/d3/ の[Keys section(今はリンク先には無い)]を見てくれ。

key functionはまた、enterとexitのselectionsを決定する。
古いデータの中に対応するkeyが見当たらない新しいデータはenter selectionとなる。
新しいデータの中に対応するkeyが見当たらなかった古いデータはexit selectionとなる。
どちらにも存在するデータは更新されるselectionとなるのだ。

Mike Bostock氏はこのスレッドの中で言及している。

f:id:muddydixon:20130825191506j:plain

焦らなくていい。あとで挙げる例と説明を見てもらえれば、多分理解できると思う。 以下の3つの例すべてで HTML paragraph element (

)を生成している。 しかし、D3.jsを使って作っているならば、諸君らが生成するいかなる他のelementで会っても同じ原則が適用される。

次の2つの例とその結果を注意深く見て欲しい。そして、例と結果の違いに着目してくれ。


例1

<!DOCTYPE html>
 <html>
 <head>
     <script type="text/javascript"
                src="http://mbostock.github.com/d3/d3.js">
     </script>
     <style type="text/css">
         p {
             font-size: 20px;
             color: orangered;
         }
     </style>
 </head>
 <body>
     <div id="example1"></div>
     <script type="text/javascript">
         pdata = [10,12,6,8,15];
 
         selectDIV = d3.select("#example1");
 
        selectDIV.selectAll("p")
             .data(pdata)
             .enter()
             .append("p")
             .text(function(d){return d;});
     </script>
 </body>
 </html>

結果1

10
12
6
8
15

例2

<!DOCTYPE html>
 <html>
 <head>
     <script type="text/javascript" 
                src="http://mbostock.github.com/d3/d3.js"
     ></script>
     <style type="text/css">
         p {
             font-size: 20px;
             color: orangered;
         }
     </style>
 </head>
 <body>
     <div id="example2">
        <p>Already existing paragraph 1</p>
        <p>Already existing paragraph 2</p>
     </div>
     <script type="text/javascript">
         pdata = [10,12,6,8,15];
 
         selectDIV = d3.select("#example2");
 
        selectDIV.selectAll("p")
             .data(pdata)
             .enter()
             .append("p")
             .text(function(d){return d;});
     </script>
 </body>
 </html>

結果2

Already existing paragraph 1
Already existing paragraph 2
6
8
15

2例のコードの違いは、d3のJavaScriptが呼び出される前に、例2では2つのparagraph element ("Already existing paragraph 1"、"Already existing paragraph 2") の存在だけだ。 そして、与えられたデータの配列では存在しているにもかかわらず、結果2では、10と12は見つけられない。なぜか?これこそが諸君が求めているものだとおもう。

1.

selectDiv.selectAll("p")selectDivの中にある全ての<p>...</p>を返す。 例1では空だし、例2ではすでにある2つのparagraph Elementが返される。

2.

.data(pdata) は2引数を引き受ける 1. data 配列 2. data 配列の要素に関連付けられている key の関数。key - これこそが enter selection を決定する。.enter().append()メソッドで指定したノードにデータ配列の中のどの要素をひもづけるかを決める、と考えればよい。

たぶん「は?key functionとかねーし。あと、keyとかいってるけど、それがどうやってenter selectionを決定してるかわかんねーし」と思うと思う。うん、当たり前だと思う。これについて説明しよう。

D3.jsの創造主がこのポストで説明しているが、key functionが.data()メソッドで明示的に指定されてない場合には、デフォルトの値として、indexが使われるんだ。この場合は、data配列のindexだ。 例えば、例1では key function が指定されていないから、10, 12, 6, 8そして15の key は 0, 1, 2, 3 そして 4となるってことだ。

この key は次のような方法でenter selectionを決定する。data配列(今の場合はpdataだ)の中の要素のkeyは既存のselection(.selectAll("p")メソッドで返されるselectionだ)のkeyと比較される。指定したdata配列の中で既存の要素のkeyと異なるkeyを持つすべての要素が、enter selectionとなるのだ。もし、既存の要素のkeyとすべてかぶった場合にはenter selectionは無い

どちらの例でもkey functionは明示的に指定されていない。つまり、keyはそれぞれの配列のindexとなる。 例1では、.selectAll("p")はからの配列を返すので、対応するkeyも空だ。ところが指定したpdata、10, 12, 6, 8, 15に対応するkeyは0, 1, 2, 3, 4だ。すべてのkeyが異なっているので、pdataのすべての要素がenter selectionになるんだ!

他方で、例2では .selectAll("p")は2つの配列を返し、これらのkeyは0, 1となる。pdataのkeyは例1同様0,1,2,3,4となっている。

10と12は既存のp要素と同じkeyを持っているので、10と12はenter selectionには含まれない!!

3.

.enter().append("p")メソッドはenter selectionの中の要素の数だけ<p>...</p>を生成する。.append()で指定した要素が生成されのだ。

例2で 10と12はenter selectionには入らなかったので、これらに対応するp要素は生成されず、結果として見ることができなかったのだ。


例2と似た例3を作ってみた。違いは、key functionを明示的に指定したことだ。これだけのことで、pdataの要素すべてが結果として現れる。

例3

<!DOCTYPE html>
 <html>
 <head>
     <script type="text/javascript" 
                src="http://mbostock.github.com/d3/d3.js"
     ></script>
     <style type="text/css">
         p {
             font-size: 20px;
             color: orangered;
         }
     </style>
 </head>
 <body>
     <div id="example3">
        <p>Already existing paragraph 1</p>
        <p>Already existing paragraph 2</p>
     </div>
     <script type="text/javascript">
         pdata = [10,12,6,8,15];
 
         selectDIV = d3.select("#example3");
 
        selectDIV.selectAll("p")
             .data(pdata, function(d){return d;})
             .enter()
             .append("p")
             .text(function(d){return d;});
     </script>
 </body>
 </html>

結果3

Already existing paragraph 1
Already existing paragraph 2
10
12
6
8
15

.data()メソッドの2つ目の引数に注目してくれ。key functionとして値自身を返すようにした。 結果として、要素の値自信がkeyとなる。つまり、要素10のkeyは10だし、12のkeyは12、6のkeyは6だ。 既存のselectionの要素のkeyは無い。結果として、例2とちがって例3では、新しいdata要素は既存の要素とは異なるkeyを持つこととなり、enter selectionになり、.enter().append("p")で生成されるんだ。

f:id:muddydixon:20130825200920j:plain