今から始めるPython その5 文字列、リスト、numpyスライシング
さて、前回までにPythonの研究向けディストーションである(Python(x,y)をインストールし、付属するIDEであるSpyderをつかってpylabの仕組みを説明、ネームスペースについて触れました。
まあ、ありがちなPythonチュートリアルではカヴァーされていないようなトピックで、初心者がつまづきそうな部分にフォーカスしながらやっていきたいとおもっているので、かなり変なPython入門シリーズになっています。
さて、いよいよnumpyを使い始めていきます。numpyは高速な配列を提供するライブラリですが、これがなかったら私はPythonは使っていなかったとおもいます。それほど重要なライブラリです。
今回は、numpyを使うにあたって重要なスライシングについて見ていきます。
Pythonで文字列、リストのスライシング
シリーズのタイトルが「今から始めるPython」なので、一応Pythonの基本を見て、numpyアレイを扱うまでの基礎を見て行きましょう。
私がPythonの基本を覚えたのは公式サイトのチュートリアルでした。いろいろチュートリアルがありますが、個人的にはこれが一番分かりやすいです。
有名なDive into Pythonも英語のウェブ版は無料で読めますが、ちょっと長めです。
Dive into PythonはPython 3用の日本語訳もあるようですね。
最近では、Mouse Vs Pythonというwxpythonの用例が沢山あるブログを書いているMike DriscollさんがKickstarterで、資金を集めて書いたPythonの入門書がありますが、こっちのほうが簡潔で良さそうに見えます。この人のブログはいつも丁寧で、分かりやすいので、きっと良さそうと思いますが、英語です。Kindle版がありますね。
で、どうせ英語ならただで読めるPython公式サイトのチュートリアルがコスパと質のバランスでやっぱりいちばんいい気がしますので、これを一緒に見て行きましょう。
まずは、3.1. Using Python as a CalculatorでPythonのインタプリタを計算機代わりにつかって、簡単な計算をしてみましょう。
まあ、3+5としたければ3+5と打てばいいという、とても当たりまえな内容で問題ないとおもいますが、剰余の計算が、MATLABだとmod(X,Y)みたいにして関数が必要なので、思わずPythonではどうやるんだっけと調べてしまうことがありますが、実はオペレーターがあって%だけでいいのが、ちょっと注意ですね。
5 % 3
とすると2が得られます。
あとは、
5/3
とすると答えがざっくり1になるのが驚いてしまうと思います。これは、もともとPythonではデータ型が保たれるような仕様であったため、Python 2系まではデフォルトでは整数同士の割り算は整数の答えになります。
MATLABから来た人は気持ち悪いし、初心者がびっくりする部分なのでPythonのバージョン3系ではちゃんと小数点のついたフロートのデータ型で答えが出るようになりました。でも、Python(x,y)をおすすめしている当ブログではPython2系をつかっていますので、整数型の答えがデフォルトです。しかし、この仕様は実は変えられるので、
from __future__ import division
と未来からのモジュールをインポートすると、先程の結果が、1.6666666666666667に変わります。これ、便利で私はよく使っています。
あとは、Pythonを起動してすぐでインポートが面倒なときは、
5/3.0
として、フロートの計算なのでフロートの結果になるようにしたりもします。
便利なのは、たまに割り算の結果の整数部だけ欲しいので、floor(5/3)なんてやることがあります。実はこれは、
5 // 3
としても同じことで、スラッシュが二重になると小数点が切り捨てになります。ちょっと便利ですね。
あとはMATLABだと階乗はハット(^)で2^10みたいにやったように記憶していますが、Pythonでは2**10のようにアスタリスクを二重にします。
あとはMATLABのansに相当するのがアンダースコア(_)で、計算機代わりに使うときは割りと便利ですね。
3.1.2. Stringsのところは、文字列のスライスのあたりまでnumpyにはあまり関係ないので説明は飛ばしますが、難しくないのでざっと読むといいと思います。"hellow" * 3とかで"hellowhellowhellow"になるのは結構斬新です。
ここで、スライスの考え方はMATLABから来たらほぼ同じなのですんなり行くと思いますが、多少違いもあるので、気をつけましょう。
word = 'Python'
として、word[0]でPにアクセスできるからわかるようにPythonではインデックスは0から始まります。MATLABは1からだったりするのでややこしいですね。
で、重要なのは
word[-1]
ですね。MATLABだとword[end-1]みたいに書くところが、endがない形でスッキリみえるけども、ひと目で初心者が分かりやすいコードはMATLABの方ですね。私はnumpyに慣れたので、スッキリしていいと思います。
word[2:5]
のように、部分的にスライスしたり、
word[2:]
のように、こっから全部という風にかけたり、
word[2::2]
ステップサイズを2に指定したりと出来ます。MATLABだとインデックスがずれて、[3:2:end]という感じでしょうか(もうMATLAB忘れている)。
このスライスはnumpyでも全く同じなので、覚えましょう。これを多次元に拡張するとnumpyのスライスになります。
3.1.3. Unicode Stringsは飛ばします。今はざっと読んでください。
3.1.4. Lists さあ、いよいよリストです。リストは、MATLABでいうCELLみたいな感じですが、こっちのほうがめちゃ便利です。Pythonにはあとはタプルとディクショナリがありますが、リストが一番よく使うもので、リストを覚えたらタプルは簡単です。
リストも文字列のときと同じようにスライスが出来ます。
squares = [1, 4, 9, 16, 25] squares[-3:]
とすると最後から3つをスライスして、
[9, 16, 25]
という結果になります。
意外と忘れるのが、コンカチネーションです。リストは実は+オペレーターであっさりとつなげます。
なので、
squares + [36, 49, 64, 81, 100]
とすると
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
という結果になります。
なんでこれが忘れがちになるかというと、リストの後ろに要素を増やそうとするときには、普通appendを使うからです。
ちょっとSpyderなどのコンソール上で、
print dir(list)
としてみるとアンダースコアが付いたものの他に
'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'
というのが出てきます。これはリストというオブジェクトが持っているメソッドで、たとえば
a = []
または
a = list()
として変数aを初期化したリストとして設定して、
a.append(3)
とするとaの中身が[3]になります。
こういう感じに最後に要素を継ぎ足していくときに使うappendはむっちゃ使いますので、発想としてはさっきのsquares + [36, 49, 64, 81, 100]をしようと思うと思わず
squares.append([36, 49, 64, 81, 100])
としてしまいたくなるわけですが、これだと結果が違って
[1, 4, 9, 16, 25, [36, 49, 64, 81, 100]]
となってしまいます。 リストはCELLのようにいろんなオブジェクトを要素として持てるので、リストの中にリストというのも可能なんですね。で、appendしたときに渡すものは一要素として追加されるので、上の様に6番目の要素はリストとしてひとまとまりで入ってしまうわけです。
どうしてもappendでやろうとおもったら一つ一つ追加する必要があるので
for element in [36, 49, 64, 81, 100]: squares.append(element)
という形になります。これは、フォーループですが、PythonではMATLABのようにendは使いません。その代わりループする内容のまとまりを表すのにインデンテーションを使います。インデンテーションとは、左側のスペースのことで、これがずれるとエラーになるという、非常に厳しいルールです。
リストには文字列やタプル、ディクショナリ、関数、クラスオブジェクト、などなどなんでも格納出来ます。
numpy超基本その1
さて、ながなかと準備してきましたが、いよいよnumpyを見ていきます。
MATLABから来た人はぜひ、NumPy for MATLAB usersというチートシートを活用しましょう。
個人的に良くまとまっているとおもった、このJ.R. Johanssonさんという方が作ったiPython notebookが参考になるので、これを一緒に見て行きましょう。あら、この方、今をときめく理研所属なのですね。
まず、
%pylab inline
としていますが、これはiPythonの特別機能である%ランチャー機能をつかっているので、我々はSpyderを使っている前提なので、かわりに
from pylab import *
の呪文を唱えましょう。
つぎに、
from numpy import *
としていますが、これはpylabと同じネームスペースですね。はっきりいって、上でpylabを呼んでいるので、必要ないのですが、まあ害はありません。
このネームスペースは、気持ち悪い人は気持ち悪いかもしれませんが、インタラクティブな解析でMATLAB代わりにするならタイピングが少ないこれでいいと思います。
そして、リストを渡してnumpy arrayをつくり、dtypeやsize、shapeを説明しています。このへんは簡単ですね。
注意すべきは
M[0,0] = "hello"
でエラーになっていることですね。これは、numpy arrayはリストとはちがって同じデータタイプのものしか入れられないという重要な制限があるからなんですね。これは、numpy arrayのメモリ上のレイアウトを最適化し、少ないメモリー領域をつかい、最小のオーバーヘッドでもってアレイの要素にアクセスするための仕様なのです。numpyの速さの秘密の一つです。
なので、たとえば自分のデータが0から255までの整数しかないとわかっている場合は、numpy arrayのデータタイプとして最適なnumpy.uint8を選んでやると一番パフォーマンスがでます。なんだかC言語をやっているみたいですね。
データタイプはアレイを作るときに
M = array([[1, 2], [3, 4]], dtype=np.uint8)
のように指定できます。我々はpylab環境にいるのでnpを省いて
M = array([[1, 2], [3, 4]], dtype=uint8)
でもオッケーです。
さらには、
M = array([[1, 2], [3, 4]], dtype='uint8')
のようにクォーテーションでくくってもよく、これはpylabでなくってもオッケーです。私は頑なにいつもnp.uint8ですが、この辺りは好みです。
さて、このMを浮動小数点型にしたいとおもったら
M = M.astype(np.float)
M = M.astype(float)
M = M.astype(np.float32)
などとして、データタイプのキャストができます。
そして、arangeやlinspaceですね。linspaceはMATLABでおなじみですね。x = arange(0, 10, 1) でarangeに渡している2番めのパラメータ10は最初のいらない要素を意味するので、0から9までを1刻みでとったアレイになるんですが、これはnumpyアレイのスライスと同じと覚えるといいと思います。あと、3つめのパラメータは省くと1になるのでこの場合省けます。
さっきの
squares = [1, 4, 9, 16, 25]
をつかってnumpyアレイaを作ってみましょう。
a = array(squares)
ここで、a[:2]とすると2は最初のいらない要素のインデックスなので、欲しいのは0,1になって、結果は
array([1, 4])
となるのですね。arangeはnumpyならではの関数なのでpython/numpyのインデックスを踏襲しているわけです。でも、linspaceはおそらくMATLABとの互換性を高めるためにつくられたかなり機能のかぶっている関数なので、動作がMATLABの様になっているわけです。
その後はざっとながして、次に便利なのは
M.nbytes
ですね。これで配列のメモリ上の大きさがバイトで分かります。MATLABではwhosというコマンドがあってよく使っていたと思いますが、numpyにはwhosみたいなのはないです。でも、Spyderにはオブジェクトヴュアーがあってまあそっちで用がたります。また、iPythonにはwhosがあったりします。iPythonは便利なのは便利ですが、Python初心者には混乱するかもしれないので、まだ説明してませんが、慣れた頃にぜひ試してみるべきツールです。
さあ、とうとうインデックシングのところまできました。リストと文字列のスライスの説明のおかげでかなり分かりやすいとおもいます。Fancy indexingがMATLABから来た人なら当然のことですが、そうでないと咀嚼するのに時間がかかりますね。
66行目に
[n for n in range(5)]
とありますが、これはリストコンプリヘンションというもので、とっても便利です。これは、ちゃんとした説明の記事が必要なくらい重要なテクニックなので、ここでは簡単にフォーループに読み替えたときに出てくる要素がリストの中身になるような感じと思ってもらえばOKです。ここではrangeというPythonのビルトイン関数をつかって0から4までの要素のリストを作っています。
ただし、
array(range(5))
とやってもarray([n for n in range(5)])と同じ結果が得られるので、リストコンプリヘンションを使う意味があまりありません。(突っ込んでばかりですみません。。)
同じことをするなら、おすすめは
B = arange(5)
で、結果は同じです。
リストコンプリヘンションの便利な使い方を一例だけ紹介しておくと、
[n for n in range(100) if n % 11 == 5]
なんてやると100までの整数で11で割った時のあまりが5になるような数を選んでリストを作れます。
次の、
row_mask = array([True, False, True, False, False]) B[row_mask]
のマスクの使い方はとても便利です。ぜひマスターしましょう。
応用としては、
B>3
とすると
array([False, False, False, False, True], dtype=bool)
という結果が得られるとおもいますが、これをつかって
B[B>3]
という風にするとアレイBの中から3より大きい要素を抜き出すことが簡単に出来ます。
array([4])
takeとかchooseって使ったことがない。Fancy indexingで十分な気がします。
さて、Linear algebraのところでたどり着きました。 これで大体半分消化しましたが、長くなったので、続きは次回にしましょう。
| 固定リンク
« 2の倍数がプログラマー心をくすぐる「2048」が面白い件。パズルゲームの著作権? | トップページ | BRIAN OKKEN氏のWhy Most Unit Testing is Wasteを読む。 »
「Python」カテゴリの記事
- デイビッド・ビーズリーのPythonコース(シカゴ5日間)のお知らせ(2014.09.08)
- Pythonでココログのサイトマップから全文配信のRSS1.0を作ってみた。(2014.09.07)
- グラフィカルで分かりやすいnumpyとmatplotlibのチュートリアル(2014.09.05)
- MeCabとScikit-learnで日本語の文章解析楽しそう。(2014.08.29)
- 今から始めるPython その1(2014.03.08)
「パソコン・インターネット」カテゴリの記事
- Bing Desktopの壁紙チェンジャーが意外にすばらしい件(2014.02.28)
- 寝ながらAndroidタブレットが使えるホルダー個人的まとめ(2014.08.31)
- Feedlyの新しいSliderが使いにくいので無効にした件。(2014.08.31)
- 2の倍数がプログラマー心をくすぐる「2048」が面白い件。パズルゲームの著作権?(2014.08.01)
- スタイリッシュで高機能になったTiddlyWiki5の使い方。(2013.11.29)
「今から始めるPython」カテゴリの記事
- 今から始めるPython その1(2014.03.08)
- 今から始めるPython その2 Spyderを使う(2014.03.11)
- 今から始めるPython その5 文字列、リスト、numpyスライシング(2014.08.02)
- 今から始めるPython その4 pylabネームスペースの解説(2014.07.26)
- 今から始めるPython その3 Site-Packagesってなに。モデュールのインストール・アンインストール(2014.03.17)
「学問・資格」カテゴリの記事
- ブラウザで文献管理してAndroidタブレットで論文読む。(2013.09.21)
- 今から始めるPython その1(2014.03.08)
- Python GUIツールキット個人的な比較のまとめ(2013.02.09)
- タビス・ラッド氏による「Pythonで音声プログラミング」(2013.04.06)
- デイビッド・ビーズリーのPythonでパブリックデータのハック(2013.04.07)
コメント