Python unicode型とstring型について

僕はPythonを使って一年も経たない入門者ですが、その短い期間で一番頻繁に悩んだ問題が、unicode型とstring型の変換エラーだと思います。

Traceback (most recent call last):
  File "/home/ryota/test.py", line 14, in <module>
    print a
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-4: ordinal not in range(128)

などというエラーをよく見かけるわけです。


コンピュータそのものが専門ではないため文字コードなど詳しくはないですが、他の用途で使っているうちにエラーの回避方法は分かったのでまとめておきます。


基本的に、
・端末に表示させたい、ファイル書き込みを行いたい…string型
・文字列処理を行うときにPythonが扱う型…Unicode

stringとunicode型の扱いですが、宣言と代入の段階では、

a="あいうえお"
print type(a) #<type 'str'>
print a #あいうえお
a=u"あいうえお"
print type(a) #<type 'unicode'>
print a #普通はERROR(後述)

で区別されます。


string型とunicode型の変換は、

#coding:utf-8
a="あいうえお"
print type(a)
print type(unicode(a,'utf-8'))
print type(a.decode('utf-8'))
a=u"あいうえお"
print type(a)
print type(a.encode('utf-8'))


そして、要注意なのがPythonのstring型とunicode型の自動変換です。
僕はこの機能を知らなかったため、string型とunicode型の違いが理解できないことがありました。

#coding:utf-8
a="あいうえお"
print "%s" % a
b=u"あいうえお"
print "%s" % b #OK
print "%s,%s" % (a,b) #ERROR

環境によると思いますが、4行目は表示できます。
しかし5行目はほぼ確実にエラーになります。
これは、unicode型をstring型に自動変換しているためだと分かりますが、文字フォーマットにstring型とunicode型を混在させるとエラーになりました。

#coding:utf-8
a=u"あいうえお"
b=u"あいうえお"
c=u"あいうえお"
d="あいうえお"
print "%s,%s,%s,%s" % (a,b,c,d.decode('utf-8'))

全てunicode型に統一するならば、表示させることができるようです。
が、これも環境よりきなようで、端末ならば受理されますが、sublime textの端末ではエラーのようです。。

Pythonの自動変換機能は場合によっては非常に分かりにくくするので気をつけるようにしています。

Amazon Product Advertising API 登録の流れ

過去の記事の中で、度々AmazonAPIを仄めかしてきました。

例えば、
巨大ネットワーク可視化ソフトCytoscape インストールと使い方 - 備忘録
Python NextworkXの使い方 - 備忘録
のネットワークにAmazonの書籍ISBNの情報を用いていました。


今回は、AmazonAPIへの登録と、Pythonを用いた簡単な使い方をまとめようと思います。

すでにネット上にたくさん情報源がありますし、細かなところはリンクを貼らせてもらいます。
2014年12月18日現在、多少Amazonの仕様がリンク先のサイトと変わったところもありますし、その点のみ書かせてもらいます。

なお、APIアフィリエイトのために提供されているので、自分のブログやTwitterを持っている必要があります。


まず、以下のサイトの通り、Amazonアソシエイトへの登録を行います。

続いて、ProductAdvertisingAPIへの登録を行います。

なお、このサイトの中段「Access Key IDとSecret Access Keyの取得」以降は微妙にAmazon側の仕様変更があります。
ProductAdvertisingAPIの登録の欄まで従って、その後は以下の文章を参照して下さい。

以上2リンク分で紹介した登録を終えたら次に、

へログインします。

f:id:alstd:20141218145357p:plain
ここをクリックしてください。 ログイン画面が表示された場合はログイン(APIのほうのアカウント)します。

f:id:alstd:20141218145429p:plain
ここをクリック。

f:id:alstd:20141218145458p:plain
ここをクリック。

f:id:alstd:20141218145521p:plain
このメッセージは無視しておくのでバツで消しておいてください。

f:id:alstd:20141218145540p:plain
Access KeysのCreate New Access Keyをクリックします。
クリックすると、Access Key IDとSecret Access Keyが生成されますが、そのウインドウは消さないでください。

f:id:alstd:20141218145615p:plain
このSecret Access Keyは、バツで消すと二度と確認できなくなります。
忘れてしまったらKeyを削除、再生成する必要があります。 この2つのKeyをメモしておいてください。

f:id:alstd:20141218145646p:plain
この○○-22でアカウント名もメモしておいて下さい。 これはAssociate Tagと呼ばれます。


以上でAccess Key ID,Secret Access Key,Associate Tagを取得できました。
今後、ソースコードやネット上のソースコードを用いてデータを取得したい場合には、以上の3つの3変数に代入して下さい。

巨大ネットワーク可視化ソフトCytoscape インストールと使い方

PythonのNetworkXやRのigraphによって巨大なネットワークの可視化を行いましたが、png出力ではノードやリンクが潰れてしまったり、リアルタイム表示すると処理が間に合わなかったりしました。

そんなとき、今開発が進められているCytoscapeというソフトを見つけたので紹介してみたいと思います。
Cytoscapeは複雑・巨大ネットワークを可視化する専門のツールで、リアルタイムで拡大しノードの属性(名前)を確認できます。
早さと滑らかさと綺麗さに驚きました。
一方、ネットワーク自体に適応させるアルゴリズムクラスタリングや中心媒介性の計算など)はできないようですが、そこだけRやPythonで計算すればよさそうです。


早速インストール方法を紹介します。(Ubuntu14.04)
まずは、Cytoscape公式サイトからダウンロードします。

WindowsMacLinuxどれも対応しているようです。

続いて、シェルスクリプトファイルがあるディレクトリで、

sudo sh Cytoscape_3_2_0_unix.sh

で完了します。


ダッシュボードなどからCytoscapeで検索して起動させましょう。
f:id:alstd:20141217163545p:plain
From Network Fileを選択すると、ネットワークのデータの場所を問われます。

ネットワークデータは統計処理ソフトR ファイルや出力の扱い方 - 備忘録のsample1.datの形式で作れます。
ただし、拡張子が.datのままだと読み込めないと言われるため、.txtにすれば大丈夫です。

小さいネットワークでは面白くないかもしれないので、
networkdata.txt - Google ドライブ
をアップロードしておきます。

f:id:alstd:20141217163646p:plain
Column1とColumn2の間を繋げたいため、画像のような設定にします。
OKを押すと次のように・・・

f:id:alstd:20141217164350p:plain
これじゃない感
もっと格好良く表示させたいですので、次のように設定を弄って下さい。

f:id:alstd:20141217164517p:plain
サイドメニューのStyleからdefault blackを選び、

f:id:alstd:20141217164610p:plain
上の画像のアイコンをクリックすると・・・

f:id:alstd:20141217164653p:plain
無事にきれいなネットワークの画像が得られました。

これはリアルタイムで表示されているため、拡大しても潰れません。
スクロールしてみると、
f:id:alstd:20141217164802p:plain
ノードに名前が付いていますね。
元のデータはAmazonの書籍のISBN(識別番号)です。
リンクは「この商品を買った人はこんな商品も買っています」の関係性から生成しています。

ノードをクリックしたり、範囲選択で複数選ぶと、
f:id:alstd:20141217165029p:plain
そのノードがハイライトされ、更にそのノードに接続するエッジも検出できます!


すごく早く処理してくれるため、可視化に関してはRやPythonを遥かに凌駕しているように感じますね。

Python NextworkXの使い方

Rを用いて巨大なネットワークを可視化しようと試みていましたが、どうも綺麗に出力できない。。

これは試作段階の情報量が少ないデータですが、Amazonの「この商品を買った人はこんな商品も買っています」をエッジとして商品を繋げたネットワークです。

https://lh6.googleusercontent.com/-CIRG_83bGzs/VJzq0-UGbdI/AAAAAAAAAAk/PDVxRPr3490/s640/1.png



特に、igraphの背景の色の指定など細かな問題があるように思います。
Rはネットワーク自体の構造を計算するのには適していると感じる一方で、ビジュアル面は他のソフトを用いてみるべきかもしれません。
その第一弾としてPython NetworkXを勉強してみたいと思います。

NetworkXはRに比べ、統計的処理などの点では劣っていて、基本的な処理しかできない一方で、Pythonのライブラリであるため、ネットワークデータの取得から可視化までを一連の流れにしたり、Cytoscapeなどのより高度な可視化ツールを扱うなど、融通の効く点で優れているそうです。

まずはインストールから。

sudo apt-get install python-networkx


こちらのサイトのコードを参考にしながら、

#coding:utf-8
from pylab import *
from networkx import *

G = networkx.Graph()
f=open("networkdata.txt","r")
for row in f:
	G.add_edge(row.split("\t")[0],row.split("\t")[1])

d=nx.degree(G)

pos = spring_layout(G)

figure(figsize=(15,15))

draw_networkx_nodes(G, pos, nodelist=d.keys(), node_size=[v * 25 for v in d.values()], node_color = 'b',label=1)
draw_networkx_edges(G, pos, width = 1)
draw_networkx_labels(G, pos, font_size = 1, font_family = 'sans-serif', font_color = 'r')

xticks([])
yticks([])
savefig("networkx.png") 

気になる出力は、
https://lh5.googleusercontent.com/-ysGPHT5rCLE/VJzq0M4U2BI/AAAAAAAAAAg/yk2qQUJRUkk/s640/networkx.png

多少綺麗になったような?
ノードのサイズを次数により変えています。

クラスタリング欲の沸いてくるような構造ですね。
元のデータはAmazonの書籍から、学術分野別に取りました。
数学関係のクラスタ、情報学関係のクラスタ、物理学関係のクラスタなどに分離していたり、複雑ネットワーク(数学と情報学に関わりが深い)や量子力学(情報学と物理学に関わりが深い)がその橋渡しのノードになっていたりしそう?
今後の課題としたいところです。



参考にしたサイト一覧です。




ああああ エロゲーの類似性関係を可視化してみた

R igraphのグラフをきれいに表示させる

巨大なネットワークをデフォルトの表示で出力すると潰れてしまう。。
plotにオプションが無いか調べたところ、わかりやすいブログを見つけました。

こちらを参考に、使うとこだけメモしておきます。

plot(g,
 vertex.size=15, #ノードの大きさ
 vertex.shape="rectangle", #ノードの形
 vertex.label=V(g)$name, #ノード属性nameをノードラベルにする。
 vertex.color=ifelse(V(g)$Faction==1,"Pink","Lightgreen"), #ノード属性Factionを用いてノードに色づけ
 vertex.label.color="gray50", #ノードのラベルの色
 vertex.label.font=2, #ノードのラベルのスタイル 1: 普通, 2: 太字, 3: 斜体, 4: 太字斜体, 5: ギリシャ文字
 vertex.frame.color="white", #ノードの枠の色
 vertex.label.cex=0.8, #ノードラベルの文字サイズ
 edge.width=E(g)$weight, #エッジ属性weightをエッジの太さとする
 edge.color="gray80", #エッジの色
 layout=layout.fruchterman.reingold) #ネットワークのレイアウト手法

これに合わせて、pngで出力するときは

png("output.png",width=1000,height=1000)

などと、サイズを変えていけばよいです!


しかし、数万ノードレベルになってくると、これでも潰れてしまう・・・どうしたものか考え中。

統計処理ソフトR ファイルや出力の扱い方

大学の授業で統計処理ソフトRを学ぶ機会がありました。

授業を履修する前から名前は聞いたことがありましたが、実際に触るのは完全に初めてです。

その授業ではExcelで用いるような各種関数に加え、グラフ理論の意味での大規模データの可視化などに用いましたが、数学・情報学に限らず便利になりそうな機能もたくさん備えています。
後々の自分、及び自分に似た入門者のために簡単にメモしておこうと思います。

sudo apt-get install R

によってRをインストールすることができます。

まず授業で必要なため、igraphというライブラリをインストールしました。
端末で

sudo R

としてRを起動した後、

install.package("igraph")

です。
Rの起動時にsudo権限をつけていないとLinux系OSでは警告が出ると思います。
MacWindows使いの人たちは必要ないかもしれません。

早速ネットワークデータを作成してみましょう。
f:id:alstd:20141216220249p:plain
このネットワークを以下のように書きなおします。

a	b
a	c
b	c
c	d
d	a

このデータをsample1.datとして保存しましょう。

続いてこのデータを読み込むRのコードです。
端末に直打ちでもできますが、ファイルを作ってみましょう。

library(igraph)
net <- read.table(file="sample1.dat",sep="\t")
g <- graph.data.frame(net,directed=TRUE)

このコードをplot.rとして保存しましょう。
library(igraph)によってigraphを読み込みます。
2行目はタブを区切り文字として、sample1.datをデータとして読み込み、netへ代入するという意味です。
そして、3行目はdirected=TRUE、つまり有向グラフとして、netをgraphの形式へと変換しています。

最後に、端末からRを起動し、

source("plot.r")
plot(g)

と入力すると、先ほどのグラフの画像が表示されているはずです。

なお、画像をpngなどで出力したい場合は、

source("plot.r")
png("sample1.png", width = 400, height = 400)
plot(g)
dev.off()

によって、カレントディレクトリにsample1.pngが出来上がっているはずです。


参考にさせてもらったサイトです!
各関数のオプションや仕様も詳しく載っています。
統計解析フリーソフト R の備忘録頁 ver.3.1