歩いたら休め

なんでこんな模様をしているのですか?

【AWS】AWSの構築・ネットワークで学んだこと

いろいろあって、AWSでEC2のインスタンス立てて、APIサーバーはプライベートのサブネットに立てて…という設定作業をしています。

多分知っている人からすると一瞬で終わるような作業ばかりなのですが、私は始めてやる作業なので詰まってばかりで困っています。 しかし、これまでの自分の不勉強を嘆いていてもしょうがありません。

ちょうど、インフラエンジニア出身の先輩にAWSのもろもろを教えていただく機会がありました。 もう困らないように、その内容を簡単にまとめておこうと思います。

何も手がかりのないまま「とりあえずEC2のインスタンス作っとくか」って作業をすると、後でサブネットの設定が変えられず、作り直す羽目になって面倒でした。

1. VPCを作り、サブネットを切る

VPCを作り、ここでパブリックとプライベートなサブネットを切ります。

docs.aws.amazon.com

2. サブネットにネットワークACLを紐付ける

ネットワークACL(Access Control List)は、要するにサブネットに対するファイヤーウォールの役割を果たすもので、「このIPのこのポートからの接続は許可する」みたいな設定ができます。

docs.aws.amazon.com

このとき、ルールを「1, 2, 3...」ではなく「100, 200, 300」と、ある程度飛ばして設定するとよいとお薦めされました。 なぜなら、switch文のように、上から順番に除外/許可ルールが適用されるため、「300番と400番の間に新しい除外ルールを設定したい」というときに、新しく350番を挿入すればよいのに対し、連番で入れていると全部ずらす必要があるためです。

3. インターネットゲートウェイを設定する

VPCの中のインスタンスは、インターネットゲートウェイを通して外のインターネットと繋がります。VPCにアタッチ(紐付け)しましょう。

設定項目はゲートウェイの名前だけです。

docs.aws.amazon.com

4. ルートテーブルを設定する

各サブネットのルーティングを担当するのがルートテーブルです。

docs.aws.amazon.com

5. EC2インスタンスを作る

スペックとコストを加味し、AMI(Amazon Machine Image)とインスタンスタイプを選びましょう。

インスタンスの初期設定時に所属するサブネットを指定するため、上記の手順を先に行っておく必要があります。 気付かずにズンズン設定すると、後で作り直す羽目になります。

docs.aws.amazon.com

設定項目の細かい注意点

ここでアドバイスとして「IAMロールは空でもいいから作っとけ!」というアドバイスを貰いました。 IAMロールによってEC2に、他のAWSのサービス(S3等)をcliやプログラムで操作できる権限が与えられるのですが、これはEC2を作るときしか設定できず、後から権限を付与することができないそうです。

また、誤って削除してしまわないよう、削除保護を付けるとベターだそうです。

ストレージの容量が多いと当然値段は上がるのですが、後からストレージの容量を減らすことはできません。 追加でストレージを設定できるため、「とりあえず低容量で作って、様子を見て追加するという運用もアリ」と聞きました。 また、「EBSは信頼性が高いが、インスタンスストアは再起動するとデータが消えるから注意せよ!」だそうです。

セキュリティグループを設定する

セキュリティーグループを設定しましょう。これはインスタンスに対するファイヤーウォールの役割を果たすものです。 サブネットに対するネットワークACLとよく似ていますが、

  • 設定する順番は関係ない(「ステートレス」と表現するそうです)
  • 「除外」の設定はなく、「許可」のみ

だそうです。

セキュリティーグループは一つのインスタンスに対して複数設定できるため、サーバーごとに設定するのではなく「Webサーバー用の設定と、ssh用の設定を用意して、必要なインスタンスに紐付けていく」とスッキリするそうです。

docs.aws.amazon.com

最後に

こちらの本を勧めてもらいました。実際参考になります。

Amazon Web Services パターン別構築・運用ガイド

Amazon Web Services パターン別構築・運用ガイド

しかし、「公式のドキュメントが一番新しくていいよ」とも先輩から教えてもらいました。

「0.0.0.0/0」みたいにIPの範囲が指定されているやつが分からない場合は、「サブネットマスク」でググると分かります。

サブネットマスク - ネットワークエンジニアを目指して

【雑記】会社に入ってわからんかったこと

社内のゆるふわ技術勉強会で発表することになったので、 最初は「入社2年目の新卒エンジニアが困ったこと」という内容にするつもりだったのですが、 愚痴っぽい内容になりすぎたのでやめました。

といってももったいないので、(一応)匿名ブログに書いておきます。

私のいる会社では、 「こういうことを成し遂げたいからITやWEBを使って実現する」 という自律的な考え方の人が多く、 「そのために必要なチャンスは用意するから、好きなようにやってね♥」 という感じの事業システムが用意されています。

しかし、自分自身はそうではなく 「求められているのは要するにこれだよね?と提案して作るプロセスが楽しかった」 というふわっとした理由でエンジニアになってしまいました。 ぶっちゃけ会社の思想に合ってなくて、 「うわー面白い文化だなー」とか「ふざけんなよ!」とか 好悪半々くらい感じながら日々過ごしています。

そんな日々を通して感じたことをここに書いておきます。

社長の言ってることがわからん

毎月社長が登壇し、 「こういう新しいチャレンジをやろうとしてるぜ!」 「売上とか営業利益が〇〇で、ここの領域が調子いいぜ!」 ということを熱っぽく語ってくれる場があります。

しかし、新卒のアホなエンジニアにはそもそも事業の知識がありません。 正直、「何かすごいことを言ってるんだな」「数字が読めないから何が良くなってるのかわかんねー」 と思ってました。

これは、事業ドメインの本を4~5冊程度読んだら解決しました。 ついでに、競合のIRのRSSが更新したら、いい感じに通知するプログラムも書いて、 「あ、あっちはこういうことやってんだ!」って知って勉強しています。

kiito.hatenablog.com

いい感じにドメイン領域のニュースを集めるアカウントも作りました。

ただ、同期の優秀な人はやはりすごくて、 社内の様々な場所で勉強する機会を作って、 自分が見ているよりもはるかに幅広いドメイン知識を身につけています。 例えば、「このマーケットの市況が良くて、自社の売上もそこに乗れている」 というところまで把握しているようです。

何を作ってるのかわからん

実際に配属されて、最初の部署では、PHPでWebサイトの開発に携わりました。しかし、

  • 「いいもの作りたい」と漠然と考えるが、何を基準に考えればいいか判断できなかった
  • 明らかに失敗した施策でも、「新しいユーザーにリーチできたから…」みたいな話を後出しで言われる

という状況で、ひたすら細かい改修をやっているけど、 何の役に立っているのか分からない・納得出来ないまま開発しており、 ストレスを感じてました。

完全に愚痴なんですが、そういうことを疑問に思っていると周りに質問すると、 「これはユーザーのためだからガンバッテ!」 みたいなことを熱っぽく語ってくれるのはいいのですが、 「いや、自分が疑問に思ってるのは、本当に役に立ってるのか、リーチするのかって点なんだけど…」 と悶々としていました。

また、(古くからあるサービスなので)レガシーな部分が多くあって、 「開発体制やコードもどこかイケてない」と感じていたのですが、 自分の技術や知識が足りず、どこがイケてないのか説明できないのも 悔しく感じてました。

これは、すぐに独立したシステムを作る部署に異動されて解決しました。 今は「マーケッターのサポートツールを作る」「彼らが喜べばOK」という 単純明快なルールがあるので気が楽です。

技術がわからん

私は、入社時点でPythonしか書けなかったし、 技術的な知識もほとんどありませんでした。 (今もちゃんとしてるとは言いがたいです。)

しかし、新卒の技術研修は微妙だったし、 周囲の先輩に聞いても「え?そんなこと当たり前でしょ?」みたいな顔で話が通じないので、 当たり前の部分から自分で勉強する必要がありました。 (話が通じなかったのは、 自分が「配列」を「リスト」、「連想配列」を「辞書」って言ってたせいかもしれないですが…)

これは「新卒エンジニア向け」って書いてる記事にあったり、 同期の強いRubyエンジニアの言ってる本をひたすら読んで対処しました。

kiito.hatenablog.com

ただ、プログラミングや座学的な部分は自分ひとりでも学びやすい (それなりにまともなコードは書けるようになった)のですが、 運用のノウハウとかエラーが起きてた場合の対処等は、個人では学びづらいです。 (と言うと、先のRubyエンジニアからは「甘えるな」って言われそうなのですが…)

どうやって身につけていこうか悩んでます。

どうやったら活躍できるのかわからん

入社時は漠然と「データ分析者の説明でよく出てくる三角形 (ビジネス理解・技術・数学)の技術の部分に近い仕事に関わりたい」 と思っていたのですが、あんまり需要・関われる場がなさそうです。

そもそも「ビッグデータ」って言われるほどデカいデータもあまりないし、 むしろいろいろな事業をまたいだ統一感の無いデータ (元々DBも集計のために設計されたものでないので仕方ないですが…)を集計すること自体が大変でした。

ただし、そのおかげで『SQLアンチパターン』や『バッドデータハンドブック』を涙を流しながら読めるようになりました。

SQLアンチパターン

SQLアンチパターン

バッドデータハンドブック ―データにまつわる問題への19の処方箋

バッドデータハンドブック ―データにまつわる問題への19の処方箋

ところで、会社で周囲を見渡すと、エンジニアの中では 「1~10まで自分で実装して責任持てるエンジニア」か 「ビジネスや企画側とすり合わせできる人」のどちらかが活躍している印象です。

ただ、前者の技術にかける偏執的な情熱にもかなわないし、 後者のように人と話すり合わせるのは得意じゃないので、 自分が活躍できるイメージは持てていません。

後輩が怖い

ものすごく優秀な後輩がいて、 ちゃんと数学的な素養を持った上でデータ分析できる人なので心強いです。 (しかも、ちゃんと目的にブレずにコミットしています。)

自分や同期が数ヶ月かけて学んだことも一瞬で吸収するし、 自分がなんとなーく過ごしてきた他部署での研修中でも、 「今日はこんなデータ見つけたぜ」みたいな日報を毎日送ってきます。

今は彼にぴったりな仕事ができてるし、 ひとまず、自分や同期が(特にデータの集計周りで)踏んだ地雷はあらかじめ説明し、 ラッパーになるプログラムやドキュメントも用意しておいたので、 あとは勝手に活躍してくれると思います。

【本】なぜエンジニアは生きづらいのか

最近のお仕事がグダグダで、「あ、今おれ上司に信用されてないな」って思うことが多いのでいろいろ読みました。

うまくいかないときは、自分の考え方や進む方向が間違っていて、どこかから別の考え方を取り入れる必要があるというのが持論です。あと、Mac Book Airが壊れて修理中で、プライベートでプログラミングしづらいので本を読むくらいしかやることがありませんでした。

上司は「顧客」だと思いなさい

直球なタイトルです。一番印象に残っているのはこのくだりです。

しかし、「成長したい」という言葉の背後には、「育ててもらいたい」という受け身の発想が見え隠れしています。これは、仕事のプロとしてはマイナスと言っていいでしょう。

給料をもらって仕事をする以上、それはまぎれもなくプロであり、その仕事ぶりは常に他人から評価される対象となります。 自分がいくらのお金を稼げるのかは、自分が決めるのではなく、常に相手が決めることになります。

最近はWEBアプリやAPIの部分の実装をしていたのですが、自分の得意分野(あくまで周りとの相対評価ですが!)のデータ周りで勝負できないかと誘導したいと思います。また、タスクの整理等を他の人に任せきりで、本当は実装する必要の無い機能に手間を書けてしまったり、周りからみても「与えられた仕事をするだけ」みたいな感じのアレでした。

今の会社はこの本にあるような「実業家」としての考え方が学びやすい環境ではあると思います。ただ、エンジニアとしては成長しづらい環境だなあと思うことがあり(糞みたいな技術的負債があったり、ノウハウが明文化されてなかったり、教育制度が整備中だったり…)、技術志向の強い若手は、もっと腕を評価される別の会社にすぐ移っちゃうんじゃないかと思ってます。

なぜアーティストは生きづらいのか

バンドマンの知り合いの印藤さんにすすめてもらった本です。若手のインディーズバンドマンのサポートもされている方で、この本のイベントにも関わっているそうです。

(余談ですが、特にインディーズのバンドマンには全然WEBでの告知等のノウハウが無いそうで、私も何かの形で手伝えないかと思ってます…が、特になにもできていません。何かアイデアがある方は連絡いただけると嬉しいです。)

一言でいうと、「練習では遅刻するくせに重要なライブでは絶対に遅刻しない奴とか、自分にとって重要なことにしか集中できないファンキーな性格の奴いるだろ?そういう奴の才能が活かせるように受け入れてこうぜ!」って本です。大学の優秀な先輩がこんな性格だったし、プログラマーにも一定数いるので共感しやすいです。

なぜアーティストは生きづらいのか? 個性的すぎる才能の活かし方

なぜアーティストは生きづらいのか? 個性的すぎる才能の活かし方

最近私はRubyプログラマーなので、「多様性は善」という感じで良かったです。

SQLアンチパターン

技術研修と称して、普段の仕事をサボっていろいろ作れるそうなのでDB周りの設計などを勉強しようと思って何冊か読んどきました。

分析用データをいろいろなところから集めるバッチ処理を作った際、「誰だよこんな適当なスキーマ決めた奴は!」「なんでテスト用のDBのテーブルスキーマが間違ってるんだよ!」という憎しみを感じていたので、自分はそういうものを作らない人間になりたいというモチベーションです。

特に面白かったのは、「2章 ナイーブツリー」で、親のコメントに対して子のコメントを残すDBのデザインパターンについての話です。ネットワークの有向グラフの枝リストのようなテーブルを別に用意して、親子関係の木構造を表現するのがエレガントでした。

あと、3章の「railsとかの影響で、とりあえずidってカラムでprimary key設定する人多いけど、ちゃんとユニークになってるキーでprimary key設定しようよ…」って話とか、徳丸本とかにも書いてるSQLインジェクションの話とかも面白かったです。

SQLアンチパターン

SQLアンチパターン

こちらの本も読んでいます。(第3まで理解してれば実務上そんなに問題ないと書いてはいましたが)○○正規化が多すぎてよくわかんないです。

達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ

達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ

Amazon Web Services 定番業務システム12パターン 設計ガイド

前述の技術研修でAWSのサービスをいろいろ使うことになるので、「とりあえず一発読んどくかー」って感じで読みました。あと、TableauとRedshiftを使った分析基盤の話も載っていたので。

Amazon Web Services 定番業務システム12パターン 設計ガイド

Amazon Web Services 定番業務システム12パターン 設計ガイド

オンラインデートで学ぶ経済学

社会科学系の面白い話が載ってそうだったので読みました。割と無難な感じの内容でした。

オンラインデートで学ぶ経済学

オンラインデートで学ぶ経済学

全然関係ないですが、知り合いのアメリカ人のオタク(私のオタク文化の師匠です)が、「今ルームシェアしてる人は、昔プロフサイトに趣味:UNDER17(桃井はるこ小池雅也の音楽グループ)って書いてる人が他にいなかったから知り合って、日本来る前から友だちだった」って言ってて、「理想のオタクフレンズや…」って感動しました。

情熱プログラマー

Javaのプロフェッショナルって言ってる人でも、Javaがどう動いてるのか理解してない人多いよね」みたいな感じで煽ってくる本でした。

同期の優秀なRubyハッカーポール・グレアムとか好き)が読んでないそうで意外でした。

情熱プログラマー ソフトウェア開発者の幸せな生き方

情熱プログラマー ソフトウェア開発者の幸せな生き方

この中で『達人プログラマー』がしきりに勧められていたので、そちらも読もうと思います。R友だちが達人プログラマーに興味を持ってるそうなので、彼が読み終わったら借りようと思います。

wakuteka.hatenablog.jp

Rubyのしくみ

情熱プログラマーを受けて「普段Ruby使ってるのに、裏の仕組みを全然理解してなかったな」と反省して読んでます。

本当はPythonで似た趣旨の本があればそちらを読みたかったのですが、無かったので、この本を読み終わったらPythonについて勉強しようと思います。Pythonは統計等のツールとして、Rubyは仕組みやコンピュータサイエンスの本も多いのは、言語の文化の違いなのかもしれませんね(単にRubyが日本生まれで詳しいだけなのかもしれませんが)。

Rubyのしくみ -Ruby Under a Microscope-

Rubyのしくみ -Ruby Under a Microscope-

【Coconut】Python互換の関数型言語Coconutはパイプ演算子が使えるよ

日頃RとPythonを使っていると、「ああ、Pythonでもパイプ演算子が使えればいいのに」「purrrライブラリみたいにラムダ式が簡単に書ければいいのに」「Pythonのジェネレーター(遅延評価するリストのようなもの)をパイプで渡せると超楽しそう」と思うことはありませんか?私は思います。

そんなニーズに応えてくれるかもしれない言語を教えてもらいました。それがCoconutです!

coconut-lang.org

Coconut is a simple, elegant, Pythonic functional programming language that compiles to Python. Since all valid Python is valid Coconut, using Coconut will only extend and enhance what you're already capable of in Python.

また、Pythonと互換性のある言語らしく、Pythonのコードがそのまま動かせる、みたいなことが書いてありました。

Rのmagrittrでおなじみのパイプ演算子も使えます。これは元ネタであるF#の書き方ですね。

"hello, world!" |> print

print関数に"hello, world!"という文字列を渡す」という意味の演算子です。

インストール

pipで簡単にインストールできました。

python -m pip install coconut

ちなみに、pyenvで入れたAnaconda 2.0.1で動かしてます。

coconut -v
# Coconut: Version 1.1.0 [Brontosaurus] running on Python 3.4.3 |Anaconda 2.0.1 (x86_64)| (default, Mar  6 2015, 12:07:41)  [GCC 4.2.1 (Apple Inc. build 5577)]

Jupyter notebookの起動

簡単なコードはjupyter notebookで試しましょう。

coconut --jupyter notebook

ブラウザ上でプログラムを試すことができます。Pythonのライブラリも呼び出すことができるようですが、jupyter notebook上から%matplotlib inlineは使えませんでした。

f:id:takeshi0406:20160625011940p:plain

Pythonからロードしたライブラリで補完はまだできないみたいです…。

パイプ演算子ラムダ式、部分適用

RとPythonプログラマーにとって気になるのが、パイプ演算子ラムダ式です。

range(10) |> map$((x) -> x**2) |> list |> print
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Pythonではlambda x: x**2と書くべきところを、Coconutでは(x) -> x**2と書けます。シンプル!

$が何なのか最初はわからなかったのですが、部分適用の記号でした(本体はfunctoolspartialみたいです)。上の例だと、map関数の第一引数の関数に2乗するラムダ式を適用し、イテレータを1つ引数とする関数を作って、それにパイプで値を渡しているようです。

関数型言語の入門書によくある感じで部分適用で遊んでみました。

print($)
# <class 'functools.partial'>

# xとyを足す関数を宣言
add = (x, y) -> x + y

# 1を部分適用する
add1 = add$(1)

# 1足す2
print(add1(2))
# 3

どうやらRのパイプ演算子みたいに、「演算子の右側の値を第一引数に自動的に突っ込む」みたいな挙動では無いようです。

演算子で折り返すときには、Pythonと同様に\を付ける必要がありました。

range(10) |> map$((x) -> x**2) |> \
 list |> print

いわゆる「関数型言語」って機能はひととおり揃ってるみたい

個人的に真新しかったのはdestructuring assignmentという機能。日本語では「分割代入」というそうです。

最近読んでいる『7つの言語 7つの世界』でPrologに似たような機能を見た気がします。また、Javascriptにも同じ機能があるみたいです。

{"list": [0] + rest} = {"list": [0, 1, 2, 3]}
print(rest)
# [1, 2, 3]

末尾最適化とか関数合成とか、「関数型言語の人がPythonに不満を持ちそうな部分がちゃんと網羅されてるなー」って感じです。

また、「関数合成が楽にできるならパイプそんなにいらなくね?」とも思うんですがどうなんでしょう?最初のパイプの例を関数合成で書くとこんな感じです。

function = print .. list .. map$((x) -> x**2) 
function(range(10))
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

雑感

私は最初、Rのdplyr + パイプ演算子 とか、Rのpurrrのような、データ分析を関数型プログラミングで楽にするようなことを期待していましたが、今のところ補完やグラフのプロットは難しく、私が現状でそのまま分析ツールとして使うことは無さそうです。

しかし、今後jupyterとの連携や、エコシステムの整備によっては素晴らしいツールになる可能性もあります。dplythonライブラリみたいに、Rと似た感覚で使いたいという機運は高まってるみたいですし。

github.com

しかし、Pythonと互換性があって、関数型の機能をフルに使ってPythonより簡潔に書ける言語と考えるとかなり遊べそうですし、使い勝手も良さそうに感じました。Pythonみたいに、再帰を使うときに再帰呼び出しの限界を気にする必要はありません。

今後もうちょっと遊んで&注目していようと思います。

【Python】駿河屋の商品一覧ページをスクレイピングするためのライブラリを作りました

アニメグッズやゲーム等、中古商品を取り扱う駿河屋の一覧ページをいい感じに取得するためのライブラリを作りました。

github.com

というのも、駿河屋には新着商品チェック機能が(ひととおり探した限りでは)無く、「新着入荷した同人CDをチェックしたい」というモヤモヤがあったためです。

後はTwitterにでも画像付きで投稿する機能を作ればbotの完成なのですが、またちょっと一作業必要なので、ひとまず今日は作業完了とします。

【Python】RプログラマーのためのPython入門

会社に優秀な後輩が入ってきて、優秀な先輩(私でゎない)の助けを得ながら、立派な分析者・Rプログラマーとして成長しつつあります。

しかし、R言語だけで全ての作業が完結できるわけではありません。手元でデータを加工・分析するための環境としては素晴らしいのですが、大規模な計算では遅かったり(パフォーマンスを上げるにしても工夫が必要だったり)、クラスベースのオブジェクト指向が無いため、プログラムが大きくなるにつれて関数の整理が難しかったり、言語としてつらい面も多いです。

また、データ分析して作ったモデルをサービスに乗せる際には別の言語を使う必要があると思います。一応、shinyというWEBアプリを作るためのライブラリもあるものの、「社外向けのサービスでバリバリ使ってるぜ!」という話は聞いたことがありません。

というわけで、R言語メインのプログラマーが、一歩進んでスクリプト言語Python)が抵抗なく使い始められるようにサポートするための記事を書きました。

こちらの記事の逆バージョンですね。

kiito.hatenablog.com

ただし、自分の環境であるPython 3.4.3 :: Anaconda 2.0.1 (x86_64)で確認していますが、バージョン(特に2.*系)によって微妙に異なる部分があるかもしれませんのでご了承ください。

Pythonの情報源・入門書

Pythonの書き方自体は難しくありません。入門書を読めば優秀なRプログラマーであればなんとなく分かると思います。 適当な入門書を読んだ後は、Dive Into Python 3 日本語版を読むと理解が深まるでしょう。

ただし、それだけで分析・開発できるようになるわけではありません。 数値計算や可視化のライブラリや、ツールとしての使い方を勉強する必要があります。

今となってはPythonのバージョン等がちょっと古いですが、それでも網羅的に紹介されています。

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理

上記の本で古くなった部分は、『IPythonデータサイエンスクックブック』でアップデートできると思います。 が、私もちゃんとこの本は読んでいないのできちんと紹介できません。

ただ、Pythonの高速化の例の中で、CやCythonに混じってJuliaが紹介されていたのは驚きました。

少し毛色は違いますが、『Pythonプロフェッショナルプログラミング』もいい本です。 PythonでのWEB開発のもろもろを書いた本で、課題管理やレビュー等、Pythonを使って開発している人が悩むことがとりあえず全部書かれているような本です。

Pythonプロフェッショナルプログラミング第2版

Pythonプロフェッショナルプログラミング第2版

Pythonの分析環境構築

Anacondaをインストールしましょう。Anacondaとはpythonディストリビューションの一つで、nupyやscipy、matplotlib等の数値計算やデータ分析で必要な主要ライブラリをオールインワンでインストールできます。

これらの記事を参考にインストールしてください。

qiita.com

antibayesian.hateblo.jp

Anacondaはデータマイニングの便利なライブラリを集めて一括でインストール・利用できるようにしたパッケージです。内包されているライブラリは様々な数値解析、機械学習自然言語処理、可視化、DB連携、データハンドリング、さらには最近話題のディープラーニングなど多岐に渡り、これを入れておけばデータマイニングを行う大抵の場面で対応できるでしょう。

RプログラマーはRStudioを利用している方がほとんどでしょうが、Pythonでデータ分析する際に便利なのがjupyter notebookです。 かつてipython notebookと呼ばれていたツールが、他言語でも利用できる形になったものです。

詳しい話は以下の記事を読んでください。

myenigma.hatenablog.com

for文でイライラしない方法

Rのプログラマーはほとんどfor文は使わないと思います。 もし使うとしても、「シミュレーションで1000ステップ計算する」というような場面に限られており、データの操作にfor文は不要です。

数値計算であればベクトル演算を使い、リストの操作もlapply等の汎関数高階関数)を利用していることと思います。 例えば、1から10までの数を2倍したベクトルを得るには、Rであれば簡単に書けます。

1:10 * 2
#  [1]  2  4  6  8 10 12 14 16 18 20

ところが、他の大抵の言語にはベクトル型は無く、リストや配列が用意されています。 そのため、for文を使って次のようなコードを書くことが多く、「Rであればもっと簡潔に書けるのに」とイライラしていることと思います。

result = []
for i in range(1, 11): # 第二引数を10にすると、1:9までしか得られないので注意!
    result.append(i * 2)
print(result)
# [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

# 第三引数で増分が指定できるから、
# list(range(2, 22, 2))でも同じ値は得られるんだけどね

このような場合、Pythonであればリスト内包表記を使うか、numpyという数値計算のライブラリを使ってベクトル型を導入しましょう。

まず、numpyを使った例です。

import numpy as np
np.arange(1, 11) * 2
# array([ 2,  4,  6,  8, 10, 12, 14, 16, 18, 20])

次にリスト内包表記です。これは関数型言語(たしかHaskell)を参考にして導入された書き方です。

Pythonではfor等の手続き型言語の書き方を流用しているのでわかりづらいですが、{f(x) | x ∈ A}(Aという集合の中のxという変数にfという計算を適用する)という数式を[f(x) for x in A]と表現しています。ちなみにHaskellの書き方のほうが、元々の数式に近くて分かりやすいです

[i*2 for i in range(1, 11)]
# [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

「何度もリストに対して計算を行う場合、リスト内包表記を使って何度もループさせると遅くなるんじゃないの?」と疑問に思うかもしれませんが、Pythonイテレータを遅延評価させる機能があります。 とりあえず覚えなくても問題ないので詳しくは説明しませんが、以下の記事や『Effective Python』を読んでください。

Python のジェネレータ (1) - 動作を試す | すぐに忘れる脳みそのためのメモ

Effective Python ―Pythonプログラムを改良する59項目

Effective Python ―Pythonプログラムを改良する59項目

はじめてのクラス

R言語プログラマーが他言語に行って戸惑うのが、クラスベースのオブジェクト指向だと思います。

たとえば、Rでの分析しか経験してこなかったプログラマーが、 「ルーチンの分析処理をバッチ処理で自動化したい!」と思って開発にも携わるようになると、 クラスという見慣れない概念が出てきて戸惑うことになると思います。

# クラスを作る
class MyClass:
    # クラスのインスタンスを作る際に呼び出させる関数(initializeの略)
    def __init__(self, config):
        # インスタンス変数に設定(conf)を保存する
        self._config = config

    # 設定をprintする
    def print_conf(self):
        print(self._config)

if __name__ == '__main__':
    instance = MyClass('variable')
    instance.print_conf()

Rのプログラマーはクラスという概念に慣れていないため、「そんなものなくても関数を細かく区切っていけばそれほど困らないよ」「継承とかカプセル化とか難しい用語がいっぱいでわからないよ(もっと難しい統計用語は使いこなしているクセして!)」と思いがちですが、実際使えると便利な機能です。

(これだけが全てだとは思いませんが、)クラスとは概ね「デカいプログラムを整理するためのもの」です。 たしかに関数を細かく区切ることで分かりやすい、似たような機能をたくさん実装する場合など、オブジェクト指向の機能を使うとコードを整理することができます。

一例として、私は最近作った、社内の様々なレポートを取得するRのコードを残しておきます。クラスの機能を導入するために、R6ライブラリを使いました

実際には「売上レポートを取得するための機能」の他に「コンバージョン率のレポートを取得する機能」などをたくさん作っており、そちらではreplaceQueryYearの代わりにreplaceQueryDateが必要だったりと、「この関数ってどこに使ってたんだっけ?」「似たような名前の関数がたくさんできちゃったよ」とごちゃごちゃしそうだったのでクラスを作って整理しました。

なんとなくクラスを覚える利点(の一つ)を感じてもらえればと思います。

# PythonではなくRだよ!
# 「SQLのファイルを読み込む」など、いろいろなクラスで共通で使う関数をまとめたクラス
AbstructReporter <- R6::R6Class("AbstructReporter",
  private = list(
    db_config = NA,

    scanQuery = function(query_path) { 
      return (
        # query_pathにあるSQLファイルからクエリを読み込む
      )
    },

    execQuery = function(sql) {
      return (
        # sqlを実行する
      )
    }
  )
)

# 売上レポートを取得するためのクラス
SalesReporter <- R6::R6Class("SalesReporter",
  inherit = AbstructReporter, # 共通で使うクラスを継承

  initialize = function(db_config) {
    private$db_config = db_config # DBの設定を
  },

  public = list(
    getSalesReport = function(target_year) {
      sql <- private$scanQuery("example/file/path.sql") %>%
        private$replaceQueryYear(target_year)
      return (
        private$execQuery(sql)
      )
    }
  ),

  private = list(
    replaceQueryYear = function(sql, target_year) {
      return (
        # SQLの対象期間(年)を置き換える
      )
    }
  )
)

# 実行プログラム
db_config <- "DBの設定"
instance <- SalesReporter$new(db_config)
sales_report <- instance$getSalesReport("2016") # 2016年のレポートを取得する

RでもR3とかR4とかいくつかのオブジェクト指向的な機能が実装されているようなのですが、『R言語徹底解説』を読んでもサッパリ分かりません。誰か助けてください。

また、「オブジェクト指向」という概念は、以下の記事を読めば分かる通り、いろいろなプログラミングの概念がごった煮になった一筋縄ではいかないものです。 いろいろな言語に触ってがんばっていきましょう(私もがんばります)。

qiita.com

Pythonは関数の第一引数にselfが必要だったり変な感じがするので、オブジェクト指向周りの概念はRubyで勉強するのが近道かなと思います(Python入門なのに)。Rubyは最初からオブジェクト指向言語を目指して作られているので、スッキリ学びやすかったです。 『メタプログラミングRuby 第2版』の前半で、Rubyオブジェクト指向の仕組みが説明されています。

Pythonな人だけど「メタプログラミングRuby」を読んでみた | TRIVIAL TECHNOLOGIES 4 @ats のイクメン日記

メタプログラミングRuby 第2版

メタプログラミングRuby 第2版

もしかするとJavaのほうがいいのかもしれませんが、私はJavaをほとんど触ったことがないので分かりません。

ファイルを読み込む

Rでファイルを読み込む場合、分析用ファイルであればread.csvや(私はよく知らないですが)データを読み込む高速なライブラリの関数を、テキストファイルであればscanreadLines等の関数を利用していると思います。

ファイルを読み込む際にプログラマーが気をつけることは、「(特にエラーが発生したときに)ファイルを閉じ忘れない」ということです。 そのため、大抵の言語ではファイルの閉じ忘れを防ぐ機能を持っています。

Pythonでは、with構文でその機能を提供しています。withブロックを抜ける(エラーが発生した場合でも)と、自動でファイルを閉じてくれます。 プログラミングでは、ファイルのインプット/アウトプットで特にエラーが発生しやすいため、このような処理が用意されています。 他の言語でも同様の機能が用意されているものが多く、Rubyの場合ブロックを使ってこの機能を実現しています

with open('./example.txt', 'r') as f:
    text = f.read()
print(text) # テキストファイルの中身を表示!

open関数の第二引数の'r'はread=読み込みの意味です。ファイルに書き込む場合は'w'にします。

csvを読み込む際は、標準ライブラリであるcsvを利用します。公式のドキュメントにあるサンプルコードを引っ張ってきました。

import csv
with open('some.csv', newline='') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

with構文についていまいちピンと来ていない場合、ちょっと古いですが、こちらの記事が参考になると思います。

reiki4040.hatenablog.com

「おれはread.csvしたいだけなのに面倒だなあ」「Rみたいにデータフレーム使いたいよ」という場合は、pandasライブラリを利用しましょう。 もちろんread.csvにあたる操作も用意されています。

import pandas as pd
sampledata = pd.read_csv('./example.csv')

また、write.csvに当たる操作は、データフレーム型の変数からto_csvメソッドを呼び出す形で操作します。

sampledata.to_csv('output.csv', index = False)

pandasの使い方の詳しくは、以下のサイトを参照してください。

myenigma.hatenablog.com

既存のライブラリを使う

R言語プログラマーは、自分で計算のロジックを実装することは(周囲から思われているよりは)あまり無く、CやC++で作成された高速なライブラリを組み合わせて分析を行うことが多いと思います。

Pythonであれば、科学計算のscipy機械学習scikit-learn等、Rほどではないですが充実したライブラリを利用することができます。 これらのライブラリについて調べれば、利用したい処理が既に実装されていることも多いでしょう。

例えば、以下の記事ではscipyによる高速フーリエ変換(FFT)の例が紹介されています。

org-technology.com

記事を見てもらえばわかると思いますが、フーリエ変換のような自分で実装するとややこしい処理が、fft関数を呼び出すだけで完了してしまっていることがわかると思います。

# 離散フーリエ変換
yf = fft(y)

プロットする

自分の持っている仮説を検証するには、集計・解析結果をグラフにプロットしてPDCAを回す必要があります。

Rでは標準でplothist等の関数を使ってグラフを可視化できますが、Pythonでは同等の機能をmatplotlibを利用します。これはMATLAB風のプロットが簡単にできるライブラリです。

Jupyter notebook上でインタラクティブに可視化でき、Rのプログラマーでも特に違和感なく利用できると思います。

hirotsuru.hatenablog.com

ただし、最近はseabornbokeh等の新しい可視化ライブラリが現れてきているようです。特にseabornは、Rのggplot2に近いおしゃれな感じのプロットが簡単にできるそうなので、今度触ってみます。

この辺の話は『IPythonデータサイエンスクックブック』にきちんと書いてあるそうです。

myenigma.hatenablog.com

qiita.com

【雑記】Operaの後継ブラウザVivaldiのクイックコマンドが便利だった

Operaの後継ブラウザのVivaldiがすごく出来が良くて驚いたという話です。

最初に結論だけ行っておくと、仕事場のWindowsではChromeFirefoxから乗り換えたのですが、Macでは未だに使いづらい部分が残っていて保留中です。

f:id:takeshi0406:20160611110951p:plain

vivaldi.com

クイックコマンドという機能が死ぬほど便利です。AtomSublime Textの機能検索、またはOSXのAlfredみたいなものを想像してもらえると分かると思います。

ふつうはF2キーがショートカットなのですが、私はAtomに合わせてCtrl+Shift+Pで実行するようにしています。

f:id:takeshi0406:20160611111236p:plain

Chroniumベース(らしい)ので、Google Chromeのアドオンもインストールできるのも強みですね。たまに互換性のないものもあるらしいですが…。

ただ、Macでは、日本語変換を確定させようとEnterキーを押した時点で検索自体が実行してしまうようです。 また、Twitter等の一部のサイトがもっさりしていました。

クイックコマンドは便利なので、(私が普段使っている)FirefoxChromeにも、アドオン等の形で同じ機能が提供されないかなと思ってます。

仕事場のWindowsではVivaldiを使おうと思います。Macはまだ厳しい部分が多いので、Firefoxにクイックコマンド的なアドオンが出るか、Vivaldiのモッサリ感が解消されることを期待しています。