読者です 読者をやめる 読者になる 読者になる

DISTRICT 37

なにか

matplotlibで2軸グラフを作る

Python

一つのグラフに複数のグラフを描くのと、評価の違う軸を合わせて描く

twinx()

これを使うだけでX軸を共有できる

twiny()

twinxがあるってことはtwinyもある

y軸が共有できたのがわかる

RapidMinerを試す

Blog

PythonとかRとかで頑張ってきたのに、こんなに簡単にできるなんて、今から始める人が羨ましい

インストール

rapidminer.com

ここからDownloadへ進んで、対象のOSにあったファイルをダウンロードする。今のところWin(32、64)、MacLinuxが対応しているので迷う事は無い。Linuxの場合はJava8が必要なので、インストールしていない場合は別途インストールする必要がある。

Installing RapidMiner Studio - RapidMiner Documentation

インストール時にメールアドレスとか電話番号とか入れてユーザ登録的な事が必要で、使用したメールアドレス宛てに承認メールが届き、それから使用可能になる。

チュートリアル

起動すると、チュートリアルを始める事ができる親切設計。やりたいことがすでにあって、ガシガシやりたい人には邪魔にも思えるが、それとなく使い方を覚える事ができるのでこれから始めるのがおすすめ。

基本的な使い方としてはデータの準備 → 前処理 → 分析手法の選択 → 結果の確認といつもやっていることを線でつないで、分析を進めていくことになる。結果は自動的にグラフが作成されたりと至れり尽くせりなことが使って数分でわかる。MicrosoftAzureとかのクラウド分析サービスをすでに使っている方にはおなじみのあれだ。

これが f:id:dragstarclassic:20170227113237p:plain

こうなるのじゃ f:id:dragstarclassic:20170227113013p:plain

あとはデータの自動視覚化とか f:id:dragstarclassic:20170227113100p:plain

サンプル

サンプルデータとしてあらかじめ「俺たちのiris」や「タイタニック」といくつかそろっているので、今までやってきた分析手法をこれで試してみるのもいい。さらに分析プロセス自体のサンプルもいくつかそろっているのでそれを眺めて、RapidMinerではこうやるのかと眺めてみるのも楽しい。

f:id:dragstarclassic:20170227101636p:plain

学習工程が短縮?

今までRやPythonで頑張って覚えてきたコマンドやスクリプトはあらかたそろっている。線をつなぐだけでそれが実現できるのだからまさにRapid。ただし、プログラミングならではの自由な処理はできないので、それは適材適所という事で使い分ける事が必要になるのかと。

f:id:dragstarclassic:20170227101242p:plain

と、ソフトを眺めていたらこんなOperatorもあったので、ある程度はプログラムを使って処理の補助ができるのかもしれない。まぁ無理してプログラムをねじ込む必要もないのですが。

とはいえ色々な分析手法があったとして、その意味を知るにはやはり何かしらの学習が必要なわけで、ノー勉強で分析ができるようになるわけではない。Rapidに分析を進めるツールとしてこれはとても秀逸だといえるのでしばらく使っていこうかと思った。

プログラミングを学ぶ意味

Blog

子供にプログラミングを習わせる親が増えているらしい。実際にプログラミング教室なんかがいくつかあって驚いた。「プログラミングを習わせる意味がどうも分からないんだよね」という人がいたのでちょっと考えをまとめてみた。

プログラミングは論理的に考える実践になる

プログラミングは論理的に考える技術を実践するということに尽きると思う。

ここにいくらかのおはじきがあり、その個数を数えてください

という問題があったとして、どのように解くのがいいのだろうか?解き方としては何通りもあると思う

回答例1:一つ一つ数える

おはじきの数が何個であろうと一つ一つ数えれば正解にたどり着く

def count(n):
  count = 0
  for i in n:
    count += 1
  print("おはじきは%d個" % count)

pythonでサンプルコードを書いてみるとこんな感じになるかと。nはリストを想定しているので、本当ならlen(n)で一撃だけど、とりあえず実直に数を数えるということで。

回答例2:2個ずつ取って、取れた回数×2とあまりの数を足す

一つ一つ数えるパターンの発展。おはじきが偶数ならとれた回数×2で答えが出て、奇数なら余りは1出るはずなのでそれを足したら全部数えられる。2じゃなくても3でも4でも5でもいい。実際に一目で数えられないくらいのモノを数えるときに「にーしーろーやーとー」と2こずつ数えてる人も多いかと。つまりそれです。

回答例3:5%くらいを取って母数を推測する

それが統計学よ!秋山仁の声が聞こえてきそうだが、これも一つの回答。おはじきの個数が多いほど力を発揮する。

この回答例があってるかあっていないかは別として、問題解決法を形にするっていうのがサンプルコードにしたようにプログラミングになるのかと思うんですよね。しかもその論理に問題があればエラーとして終了するし、問題が無ければ答え合わせができる。

論理的思考の技術の本がずらずらと本屋なり図書館なりに並んでいて、いろいろとノウハウがあると思うけどそれを実践で試せるっていうのがプログラミングのいいところかと。こういった部分のトレーニングは数学(算数)の問題集を解くのでもいいとは思うけど、パソコンでゲームのようにやれば興味が湧くのだろうというのが根幹にあるのだと思いますね。

ちなみに、効率のいい方法というのがいくつかあって、それはアルゴリズムと呼ばれている。

学校でプログラミングが必修に?

小学校段階におけるプログラミング教育の在り方について(議論の取りまとめ):文部科学省

リンク先の中でも論理的思考が云々という話が当然出ています。人材育成とかも重要かとは思いますが、このポイントを見過ごしている方が以外にいないのかなと思っています。このプログラミング教室に通わせる親が増えているという状況はぜひこのポイントを汲み取っていただきたいなと思います。

教育とプログラミング

こんなの大人になっても使わねーよと呟くことはどの時代のどの世代の子供にもあると思う。プログラミングが必修化したらきっと全国の小学生に言われると思っています。確かにプログラムに関して言えば結局は何を作るかのほうが大切だと思うんですよね。プログラムはただの道具というか部品なので。では何かを作るために、どのようにアイデアを出すか?それには結局基礎となる「勉強」が必要になるんですよね。「算数」だけじゃなく「国語」も必要だし「社会」も必要。しかもそれは大人にならないと気付かなったりする、いわゆる教養ってやつですね。

lootone.exblog.jp

たけしもこのように言っているそうです。

ということで個人的な感想を言えば、プログラミング教室ってのにあまり必要性を感じないというのが正直なところですね。もちろん自身がプログラマーなので、自分で教えられるよという事もあります。論理的思考という面ではプログラミングを通して鍛えることもないんではないかなと思っています。数学の問題集でもいいし、ディベートでもいいし、なんならゲームだっていいし、教材はいくらでもあるのかと。

ですがいろいろなことに興味を持たせるという事に対しては否定はしませんし、必要だと思っています。それがプログラムだったら、親としてというよりもプログラマーとしてうれしい事だというだけですね。

なんだか取りまとめのない論理的思考が抜けてる文章を書いてしまったなと反省

MySQLの小ネタ

Blog

普段はWorkbenchとかプログラムとかからDBを扱っているので、CUIではあまり見ない。mysqlをふとした時にターミナルで見たりすると面食らう事があるので、いくつか使えそうなネタを調べた

PAGERの指定

SELECTの結果とかをPAGERで見ることが出来る。コンソールでSELECTの結果を見ると、レイアウトがグチャグチャになってしまうので、少しでも見やすくするためにPAGERを使って見る。

mysqlを始めるときに指定するやり方

mysqlを始めるときにpagerを指定して、各種結果を標準出力からpagerに渡すことが出来る

$ mysql -u username -p --pager='less -S'

mysqlモードに入った後からの指定

最初にpagerの指定を付け忘れても、後から指定、変更ができる

mysql > pager less -S

PAGERの終了

どんな結果もpagerで出るようになるのだが、逆にpagerだと見にくいと感じるもある。たとえばshow tablesとか、describe tableして結果を見ながらSQLを書こうかなと思っていてもpagerで出てしまうので、標準出力には残らない。

mysql > nopager

これでpagerの指定を解除できる

参考:

qiita.com

結果を縦で見る

\Gを付けることで結果を横から縦にすることが出来る

mysql > SELECT foo, bar from baz\G

クエリの末に\Gを書くと

|foo        |bar     |
+-----------+--------+
|hoge       |fuga    |
|hogehoge   |piyo    |

いつものこんな感じの出力が

********* 1. row **********
foo:hoge
bar:fuga
********* 2. row **********
foo:hogehoge
bar:piyo

こうなる。

JSON形式で表せたらいいなぁなんて思ったりもしたけど、今のところその機能は無い。

EDITORで編集

当然クエリなんかを書く際はエディタを使ったほうが編集しやすいに決まってる。ということでエディタを起動してクエリを編集

mysql > edit

こうすると環境変数EDITORに指定されているエディタが起動する。僕の場合はvimが起動し、クエリを書いて保存、終了。これで即クエリを実行してくれれば便利なんだけど、改めてセミコロンを打たないと実行されない。正直ちょっと使いづらいかなぁという印象。editと打つだけで直前のクエリをバッファに出してくれるのはちょっと便利。

ファイルからクエリ実行

それならばあらかじめ編集してあるファイルを使えばいいということで、ファイルからクエリを実行する方法。

mysql > source hoge.sql

パスの補完をしてくれないのがただただつらい。

shellコマンド実行

ソースから実行するにしても、そもそもどこにいるんだっけ?とカレントディレクトリを調べたい時にmysqlモードからshellコマンドを実行する事が出来る。

mysql > \! ls -la

shellコマンドが実行できるということは、俺たちのvimももちろん実行できるのでファイルの編集もへっちゃら。

mysql > \! vim hoge.sql

ただ、.bashrcとかに書いたエイリアスが効かないのが何ともいえない。とりあえずこのshellコマンドが実行できる事がわかればいろいろ捗りそう。

help

こうやって調べたことは体に刻み込まれる前に忘れてしまうものですが、まぁ、ヘルプを見たら大体出てるので忘れても思い出しやすいですね。

mysql > help
List of all MySQL commands:
Note that all text commands must be first on line and end with ';'
?         (\?) Synonym for `help'.
clear     (\c) Clear the current input statement.
connect   (\r) Reconnect to the server. Optional arguments are db and host.
delimiter (\d) Set statement delimiter.
edit      (\e) Edit command with $EDITOR.
ego       (\G) Send command to mysql server, display result vertically.
exit      (\q) Exit mysql. Same as quit.
go        (\g) Send command to mysql server.
help      (\h) Display this help.
nopager   (\n) Disable pager, print to stdout.
notee     (\t) Don't write into outfile.
pager     (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print     (\p) Print current command.
prompt    (\R) Change your mysql prompt.
quit      (\q) Quit mysql.
rehash    (\#) Rebuild completion hash.
source    (\.) Execute an SQL script file. Takes a file name as an argument.
status    (\s) Get status information from the server.
system    (\!) Execute a system shell command.
tee       (\T) Set outfile [to_outfile]. Append everything into given outfile.
use       (\u) Use another database. Takes database name as argument.
charset   (\C) Switch to another charset. Might be needed for processing binlog with multi-byte charsets.
warnings  (\W) Show warnings after every statement.
nowarning (\w) Don't show warnings after every statement.
resetconnection(\x) Clean session context.

For server side help, type 'help contents'

けどhelp pagerとかしてもなんも出ないので、helpに期待しすぎてもです。

Scrapyのコツ

Python

Scrapyを作ってていくつかコツをつかんだ気がする。といっても処理側の話なので、xpathをマスターしないことにはScrapyが作れないことには変わりない。

Spiderのコツ

itemをitemクラスに格納する際にはyieldをうまく使うといい。

前回やったRSSのようにデータが繰り返しの構造になっている場合には、forループを回している最中で処理がyieldに到達するとpipelineへと処理が移行する。pipelineの処理が終わると、またSpiderにおいてforループの続きが行われる。

dragstar.hatenablog.com

前回記事ではpipelineに関する処理は省略したが、SpiderとpipelineはSpiderでitemにデータを全部いれてからpipelineでforループを使って処理をしていた

  • 変更前
# your Spider
item['title'] =response.xpath('//item/title/text()').extract()
item['link'] =response.xpath('//item/link/text()').extract()
yield item
# your pipeline
title = item['title']
link = item['link']
for (t, l) in zip(title, link):
  print("title", t)
  print("link", l)

これをSpiderでforループを回して途中でyieldするようにして、pipelineではforループを書かないように変更した。

  • 変更後
# your Spider
rss = response.xpath('//item')
for sel in rss:
  item = HatenaHotentryItem()
  item['title'] = sel.xpath('title/text()').extract()[0]
  item['link'] = sel.xpath('title/text()').extract()[0]
  yield item
# your pipeline
title = item['title']
link = item['link']
print("title", title)
print("link", link)

これでforループの途中でpipelineに処理が移行し、pipelineがitemを使って何かしらの処理ができるようになる。どっちでforループを書くのかってだけといえばそのとおり。

pipelineのコツ

コツってほどでもないけど、上のSpiderに合わせて変更をする。pipelineではSpiderのライフサイクルに合わせて処理の定義ができる。

Item Pipeline — Scrapy 1.3.0 documentation

具体的にはSpider開始時、処理中と終了時の処理を定義できる。たとえば、Spider開始時にRDBとのコネクションを張って、Spider終了時にコネクションを切るといった事もできる。

class YourPipeline(object):

  def __init__(self):
    # いわゆるinit。pipelineがインスタンス化されたときに呼び出される
    # pipeline特有のものではなくpython標準なので、特に解説するようなことはない

  def open_spider(self, spider):
    # スパイダーが起動したときに呼び出される
    # DBへのコネクションを張ったりとか

  def process_item(self, item, spider):
    # スパイダーがyieldした時に呼び出される
    # itemを使って具体的に処理をする

  def close_spider(self, spider):
    # スパイダーが終了したときに呼び出される
    # トランザクションをcommitしたりDBをcloseしたりとか

処理を変えるとoutputするjsonのデータ構造も変わるので、好きなほうに変えるといいと思う。jsonがどういった構造のほうが扱いやすいかで決めたらいい。

ScrapyでRSSをスクレイピング

Python

RSSリーダがすでにあるのに、スクレイピングをするなんて、、、いや、余計なことは考えない!!

スパイダーを作ってアイテムに入れるまで

今回のお題としては、はてぶの人気エントリのRSSを取ってきてアイテムに入れるまで。パイプラインに関しては今回は扱わない。

はてなブックマーク - 人気エントリー

まずはプロジェクトの作成

scrapy startproect hatena_hotentry

続いてスパイダーの生成

cd hatena_hotentry
scrapy genspider HotentrySpider feeds.feedburner.com

ここまでは何の問題もなく終わる。

それからシェルを使ってxpathの確認

scrapy shell http://feeds.feedburner.com/hatena/b/hotentry

例によってソースを確認して(※データは記事作成時のもの)

~前略~
  <item rdf:about="http://anond.hatelabo.jp/20170118083140">
    <title>映画館でわざわざ観る必要がない問題</title>
    <link>http://anond.hatelabo.jp/20170118083140</link>
    <description>「この世界の片隅に」はわざわざ映画館で観る理由がない。映画館で観る人はとにかく褒めたいアーリーアダプターと話題に乗っかりたいブロガーさんだけである。 いずれYoutubeかAmazonビデオでなら観るだろう。そしてレビューに「素晴らしかった!」とか書くんだろう。 この手の話はここ10年映画が衰退している理由でもある。 BDの普及、レンタル屋、テレビの高精細大画面化。 キネマ旬報はこの流れとともにお...</description>
    <content:encoded><![CDATA[<blockquote cite="http://anond.hatelabo.jp/20170118083140" title="映画館でわざわざ観る必要がない問題"><cite><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fanond.hatelabo.jp%2F" alt="" /> <a href="http://anond.hatelabo.jp/20170118083140">映画館でわざわざ観る必要がない問題</a></cite><p>「この世界の片隅に」はわざわざ映画館で観る理由がない。映画館で観る人はとにかく褒めたいアーリーアダプターと話題に乗っかりたいブロガーさんだけである。 いずれYoutubeかAmazonビデオでなら観るだろう。そしてレビューに「素晴らしかった!」とか書くんだろう。 この手の話はここ10年映画が衰退している理由でもある。 BDの普及、レンタル屋、テレビの高精細大画面化。 キネマ旬報はこの流れとともにお...</p><p><a href="http://b.hatena.ne.jp/entry/http://anond.hatelabo.jp/20170118083140"><img src="http://b.hatena.ne.jp/entry/image/http://anond.hatelabo.jp/20170118083140" alt="はてなブックマーク - 映画館でわざわざ観る必要がない問題" title="はてなブックマーク - 映画館でわざわざ観る必要がない問題" border="0" style="border: none" /></a> <a href="http://b.hatena.ne.jp/append?http://anond.hatelabo.jp/20170118083140"><img src="http://b.hatena.ne.jp/images/append.gif" border="0" alt="はてなブックマークに追加" title="はてなブックマークに追加" /></a></p></blockquote><img src="http://feeds.feedburner.com/~r/hatena/b/hotentry/~4/8vfCvvBcSzw" height="1" width="1" alt=""/>]]></content:encoded>
    <dc:date>2017-01-18T08:57:56+09:00</dc:date>
    <dc:subject>エンタメ</dc:subject>
    <hatena:bookmarkcount>197</hatena:bookmarkcount>
  </item>
  <item rdf:about="https://note.mu/wakusei2nd/n/n562b7d525897">
    <title>なぜ日本が世界共通語「Emoji」を生み出したのか、そしてその影響とは/古川健介『TOKYO INTERNET』|PLANETS|note</title>
    <link>https://note.mu/wakusei2nd/n/n562b7d525897</link>
    <description>なぜ日本が世界共通語「Emoji」を生み出したのか、そしてその影響とは/古川健介『TOKYO INTERNET』 ★☆★☆★☆★☆★☆★☆★☆★☆★☆ こちらの記事は、1/19(木)24:00までの期間限定で全文無料でお読みいただけます! ★☆★☆★☆★☆★☆★☆★☆★☆★☆ Daily PLANETS では毎月第2水曜日に、古川健介さんの連載『TOKYO INTERNET』を配信しています。連載...</description>
    <content:encoded><![CDATA[<blockquote cite="https://note.mu/wakusei2nd/n/n562b7d525897" title="なぜ日本が世界共通語「Emoji」を生み出したのか、そしてその影響とは/古川健介『TOKYO INTERNET』|PLANETS|note"><cite><img src="http://cdn-ak.favicon.st-hatena.com/?url=http%3A%2F%2Fnote.mu%2F" alt="" /> <a href="https://note.mu/wakusei2nd/n/n562b7d525897">なぜ日本が世界共通語「Emoji」を生み出したのか、そしてその影響とは/古川健介『TOKYO INTERNET』|PLANETS|note</a></cite><p><a href="https://note.mu/wakusei2nd/n/n562b7d525897"><img src="http://cdn-ak.b.st-hatena.com/entryimage/316512078-1484693699.jpg" alt="なぜ日本が世界共通語「Emoji」を生み出したのか、そしてその影響とは/古川健介『TOKYO INTERNET』|PLANETS|note" title="なぜ日本が世界共通語「Emoji」を生み出したのか、そしてその影響とは/古川健介『TOKYO INTERNET』|PLANETS|note" class="entry-image" /></a></p><p>なぜ日本が世界共通語「Emoji」を生み出したのか、そしてその影響とは/古川健介『TOKYO INTERNET』 ★☆★☆★☆★☆★☆★☆★☆★☆★☆ こちらの記事は、1/19(木)24:00までの期間限定で全文無料でお読みいただけます! ★☆★☆★☆★☆★☆★☆★☆★☆★☆ Daily PLANETS では毎月第2水曜日に、古川健介さんの連載『TOKYO INTERNET』を配信しています。連載...</p><p><a href="http://b.hatena.ne.jp/entry/https://note.mu/wakusei2nd/n/n562b7d525897"><img src="http://b.hatena.ne.jp/entry/image/https://note.mu/wakusei2nd/n/n562b7d525897" alt="はてなブックマーク - なぜ日本が世界共通語「Emoji」を生み出したのか、そしてその影響とは/古川健介『TOKYO INTERNET』|PLANETS|note" title="はてなブックマーク - なぜ日本が世界共通語「Emoji」を生み出したのか、そしてその影響とは/古川健介『TOKYO INTERNET』|PLANETS|note" border="0" style="border: none" /></a> <a href="http://b.hatena.ne.jp/append?https://note.mu/wakusei2nd/n/n562b7d525897"><img src="http://b.hatena.ne.jp/images/append.gif" border="0" alt="はてなブックマークに追加" title="はてなブックマークに追加" /></a></p></blockquote><img src="http://feeds.feedburner.com/~r/hatena/b/hotentry/~4/Yrhv1rRQwes" height="1" width="1" alt=""/>]]></content:encoded>
    <dc:date>2017-01-18T07:51:51+09:00</dc:date>
    <dc:subject>テクノロジー</dc:subject>
    <hatena:bookmarkcount>287</hatena:bookmarkcount>
  </item>
~後略~

なるほどね、itemタグからのtitleタグなのねと以下のように入れたら何も出なかった

In [1]: response.xpath('//item/title/text()').extract()
Out[1]: []

公式のドキュメントにそれっぽい記述があった。

Selectors — Scrapy 1.3.0 documentation

Once in the shell we can try selecting all <link> objects and see that it doesn’t work (because the Atom XML namespace is obfuscating those nodes):

But once we call the Selector.remove_namespaces() method, all nodes can be accessed directly by their names:

どうやらscrapyする相手がxmlとかrssとかatom形式の場合だと名前空間が邪魔して、素直に読めないからひと手間必要ということが分かった。

ということで以下のようにする

In [2]: response.selector.remove_namespaces()
In [3]: response.xpath('//item/title/text()').extract()

Out[3]: ['映画館でわざわざ(略)

これでOK。rssなどをscrapeした場合はresponse.selector.remove_namespaces()しないとデータが見えない。

ついでに<dc:subject>とかなってるタグ。そのままでは取れないけど、dcとかの前部分を無視してコロン以降の後部分を使えばデータが取れる

In [4]: response.xpath('//item/subject/text()').extract()

Out[4]: ['エンタメ(略)

shellで検証した結果を受けて編集したSpiderとItem

  • Spider
  • Item

最後にcrawlが動かせれば出来上がり

scrapy crawl Hotentry

(結果略)

scrapyを作る際はshellの検証が必須ですねぇ

関連記事

dragstar.hatenablog.com

dragstar.hatenablog.com

20161228アンテナ

Blog

自身のアンテナを書くのをマネしてみた。気が付いたらまた見直そう

アンテナ

今回はPython関係多めかな。