バナナでもわかる話

開設当初は計量経済学・統計学が専門の大学院生でした。今はデータを扱うお仕事をしています。統計学・経済学・投資理論・マーケティング等々に関する勉強・解説ブログ。ときどき趣味も。極力数式は使わずイメージで説明出来るよう心掛けていますが、時々暴走します。

python入門 pandasを使ったデータフレームの扱い

pythonには、Seriesというデータ構造とDataFrameというデータ構造があります。

データ分析において、これらのデータ構造に関する扱いを理解しておくことは必須ですので、簡単に入門記事を書いておこうと思います。


目次

スポンサーリンク


pandas

pandasはデータ分析に便利なデータ構造と、簡単に分析が行えるツールを備えています。

Rユーザーであればデータフレームは馴染み深いとは思いますが、pythonではpandasを入れないとデータフレームは使えません。


ということでpandasを読み込みましょう。

import pandas as pd

慣例に従い、pdという名前で読み込みます。


Seriesの利用

pandasではシリーズというデータ構造を使うことができます。

In : seq0=pd.Series([1,2,3])
     print(seq0)
Out : 
0    1
1    2
2    3
dtype: int64

リスト[1,2,3]を入力したはずなのに、一番左の列には0,1,2という値が入っています。
これはインデックスです。Seriesと普通の数字の列との大きな違いはこのインデックスにあります。

例えばインデックス0の値1を取り出したければ次のように入力することで取り出すことができます。

In : seq0[0]
Out : 1

値の入っている列だけを取り出したい場合はvalues,インデックスを取り出したい場合はindexで取り出せます。
取り出された値はnumpyのndarrayで取り出されます。

In : seq0.values
Out : array([1, 2, 3])

In : seq0.index
Out : RangeIndex(start=0, stop=3, step=1)


インデックスが0,1,...だと正直リストとの違いがあまりわからないので、インデックスを指定してSeriesを出力してみましょう。

In : seq1=pd.Series([1,2,3],index=["a","c","b"])
     print(seq1)
Out : 
a    1
c    2
b    3
dtype: int64

インデックスがa,c,bに変わりました。

発想としては辞書型に似ていますね。ちなみに辞書型もSeriesに変換できます。

In : seq2 = pd.Series({"a":1,"b":2})
     print(seq2)
Out : 
a    1
b    2
dtype: int64


インデックスの列を変更することも当然できて

In : seq0.index = ["q","w","e",]
     print(seq0)
Out : 
q    1
w    2
e    3
dtype: int64
Seriesを扱うメソッド

インデックスを使って並び変えたい!と思った場合、reindexで並べなおすことができます。
存在しないインデックスの場所にはデフォルトではNaNが入ります。fill_valueで変更することもできます。

In : seq0.reindex(["q","e","w","d"])
Out : 
q    1.0
e    3.0
w    2.0
d    NaN
dtype: float64

DataFrameの利用

Seriesを行列のような形に拡張して、行だけではなく列にも名前をつけたい場合があると思います。
そのような場合に利用するのがデータフレームです。Seriesと同様、辞書型から作成してみます。

In : DF1 = pd.DataFrame({"a":[1,2,3,4],"b":[5,4,3,2]})
     print(DF1)
Out : 
   a  b
0  1  5
1  2  4
2  3  3
3  4  2

列に名前がつきました。Rユーザーであれば、馴染深い形になってきましたね。

値の取り出し方ですが、まず列を指定する場合は簡単で、次のように行います。

In : DF1[["a","b"]]
Out : 
   a  b
0  1  5
1  2  4
2  3  3
3  4  2

In : DF1["b"]
Out : 
    b
0  5
1  4
2  3
3  2

In : DF1["b"][0]
Out : 5

行のみを指定する場合は、スライスします。

In : DF1[0:2]
Out :
   a  b
0  1  5
1  2  4


こんなこともできます

In : DF1[DF1>3]=100
Out : 
     a    b
0    1  100
1    2  100
2    3    3
3  100    2

python入門 Numpyを使った行列の計算

今日はNumpyパッケージに入っているndarray型変数の扱いについてやっていきます。


目次

スポンサーリンク


Numpy

Rと違って、pythonは行列計算の基盤が通常整っていません。
例えば、リストで行列っぽいものを以下のように作ってみたとしても

M1 = [[1,2,3],[2,3,4],[5,6,7]]
M2 = [[2,3,4],[3,4,5],[6,7,8]]

足し算さえできません。

In : M1 + M2
Out : [[1, 2, 3], [2, 3, 4], [5, 6, 7], [2, 3, 4], [3, 4, 5], [6, 7, 8]]

まあ、リストなので。


そういうわけで、こうした問題を回避するために利用するのがNumpyです。
Numpyは次のようにインポートします。
npという名前をつけるのが慣例です。

import numpy as np

ndarray

では、行列計算を行うにはどうしたら良いのでしょう。
先ほどのリストを使って計算してみます。

M1 = [[1,2,3],[2,3,4],[5,6,7]]
M2 = [[2,3,4],[3,4,5],[6,7,8]]

行列計算はNumpyのndarrayによって行います。

In : M1 = np.array(M1)
     M2 = np.array(M2)
     print(M2)
Out : 
array([[2, 3, 4],
       [3, 4, 5],
       [6, 7, 8]])

このように変換してやると、例えば先ほどの足し算も正しく計算できます。

In : M1 + M2
Out : 
array([[ 3,  5,  7],
       [ 5,  7,  9],
       [11, 13, 15]])
色々なarrayの生成

様々な方法でndarrayを生成することができます。

arrangeによるベクトルの生成

In : arange(1,5)
Out : array([1, 2, 3, 4])

zerosによる零ベクトルの生成

In : zeros(3)
Out : array([ 0.,  0.,  0.])

eyeによる単位行列の生成

In : eye(3)
Out : 
array([[ 1.,  0.,  0.],
       [ 0.,  1.,  0.],
       [ 0.,  0.,  1.]])

reshapeによるベクトルから行列への変換

In : zeros(10).reshape(2,5)
Out : 
array([[ 0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.]])

他にもいろいろありますが、要はこんな感じで色々な行列やベクトルを生成できるということを知っておくことが重要です。

whereによる特殊な行列の生成

例えば、M1の5以上のところだけ1,それ以外は0になっている行列を生成したいと言った状況があるかもしれません。
そのような場合はwhereメソッドを利用します。

In : where(M1>=5,1,0)
Out : 
array([[0, 0, 0],
       [0, 0, 0],
       [1, 1, 1]])

M1>=5の部分は実は次のような行列になっています。

In : print(M1>=5)
Out : 
array([[False, False, False],
       [False, False, False],
       [ True,  True,  True]], dtype=bool)

つまり、whereはTrue or Falseが入っている行列に対して、Trueの部分に2個目の引数、Falseの部分に3個目の引数が入るわけですね。



計算例

足し算だけでなく、行列っぽい計算はだいたいできます。
例えば転置したければTを利用します。

In : print(M1)
Out : 
array([[1, 2, 3],
       [2, 3, 4],
       [5, 6, 7]])

In : M1.T
Out: 
array([[1, 2, 5],
       [2, 3, 6],
       [3, 4, 7]])

内積はdotでいけます。

In : print(M2)
Out : 
array([[2, 3, 4],
       [3, 4, 5],
       [6, 7, 8]])

In : np.dot(M1,M2)
Out : 
array([[ 26,  32,  38],
       [ 37,  46,  55],
       [ 70,  88, 106]])

全体にルートをかけたりexpの中に入れたりすることも簡単です。

In : np.sqrt(M1)
Out : 
array([[ 1.        ,  1.41421356,  1.73205081],
       [ 1.41421356,  1.73205081,  2.        ],
       [ 2.23606798,  2.44948974,  2.64575131]])
In : np.exp(M1)
Out :
array([[    2.71828183,     7.3890561 ,    20.08553692],
       [    7.3890561 ,    20.08553692,    54.59815003],
       [  148.4131591 ,   403.42879349,  1096.63315843]])

Rユーザーからすると、行列計算でわざわざパッケージを使わないといけないなんて!となるかもしれませんが、まあ最初にNumpyをimportするだけで済む話なので、あまり気にせず使っていきましょう。

python入門 リストの処理

pythonには、リストというデータ構造が存在します。

今回は、リストの基本的な処理についてまとめていきます。


目次

スポンサーリンク


リスト

まず、適当にリストを作ります。

ListSample0 = ["X","Y","Z"]

このように大括弧を使うと、リストが出力されます。一応ちゃんとリストになっているか確認

In : type(ListSample0)
Out : list

ちなみに、リストの要素は異なったものを入れることもできますし、リストの中にリストを入れることもできます。

リストの参照と取り出し

リストの中の値を取り出すときは、インデックスを指定してやります(0始まりです)。

In : ListSample0[0]
Out : 'X'

ちなみに、スライスした場合は、リストのままで出てきます。

In : ListSample0[0:1]
Out : ['X']

In : ListSample0[0:3]
Out : ['X', 'Y', 'Z']

代入するときも、インデックスを指定するだけでいけます。
以下は「<-」で代入していますが、python2の場合「=」を使わないとエラーが出るので注意。

In : LS0 <- ListSample0
     LS0[1] <- "YYY"
     print(LS0)
Out : ['X', 'YYY', 'Z']

リストを扱うメソッド

リストの要素の追加

リストは要素を変更したり、削除したり、追加したりすることができます。
追加を行う場合、インデックスを使うとエラーが出ます。

この場合はappendメソッドを使いましょう。

In : LS0.append("A")
     print(LS0)
Out : ['X', 'YYY', 'Z', 'A']

インデックスを指定して、挿入したい場合はinsertメソッドを利用します。

In : print(ListSample)
Out : ['X', 'Y', 'Z']

In : ListSample.insert(1,"YYY")
     print(ListSample)
Out : ['X', 'YYY', 'Y', 'Z']
リスト同士の結合

リストが2つあるような場合を考えます。

In : LS2 <- [1,2,3]
     print(LS0,LS2)
Out : ['X', 'YYY', 'Z', 'A'] [1, 2, 3]

この2つをくっつけて一つのリストにしたい場合、extendメソッドを利用します。

In : LS2.extend(LS0)
    print(LS2)
Out : [1, 2, 3, 'X', 'YYY', 'Z', 'A']

ちなみに、+=でもいけます。

In : LS2+=LS2
     print(LS2)
Out : [1, 2, 3, 'X', 'YYY', 'Z', 'A', 1, 2, 3, 'X', 'YYY', 'Z', 'A']
要素の削除

削除したい場合は、del またはremoveを利用します。
delでは、インデックスを指定して次のように利用します。

In : print(LS0)
Out : ['X', 'YYY', 'Z', 'A']

In : del LS0[2]
     print(LS0)
Out : ['X', 'YYY', 'A']


removeでは、値を直接入力します。

In : LS0.remove("YYY")
     print(LS0)
Out : ['X', 'A']


ちなみに、取り出して削除することもできます。

In : x=LS0.pop(0)
     print(LS0)
Out : ['A']

In : print(x)
Out : 'X'
並び替える

昇順に並び替えることもできます。

In : LS3 = [3,2,5,5,4]
     print(LS3.sort())
Out : [2, 3, 4, 5, 5]

RとPythonでハッシュ値を出力する方法

少し前にハッシュ値について記事を書きました。
bananarian.hatenablog.com




実はRとPythonを使ってハッシュ値を出力することも出来ます。

今回も「banana」を入力してハッシュ値を出してみます。


Rの場合

opensslパッケージというパッケージで簡単に出力することが出来ます。

install.packages("openssl")


opensslパッケージには様々なハッシュ関数が用意されており、sha1やmd5など有名なものもいくつかあります。

>library(openssl)
> sha1("banana")
[1] "250e77f12a5ab6972a0895d290c4792f0a326ea8"
> sha224("banana")
[1] "8f5901a4a0a2d72ff9882e63c08d4c32b3eaa3683b6e5bfc0ca03e86"
> sha256("banana")
[1] "b493d48364afe44d11c0165cf470a4164d1e2609911ef998be868d46ade3de4e"
> sha384("banana")
[1] "92f7818b31b9936b90a5178e811979ef3ba68a14b57e8362424d54446f31ad2a249e4306628ad33ccb28b3e9dc5e043e"
> sha512("banana")
[1] "f8e3183d38e6c51889582cb260ab825252f395b4ac8fb0e6b13e9a71f7c10a80d5301e4a949f2783cb0c20205f1d850f87045f4420ad2271c8fd5f0cd8944be3"
> sha2("banana", size = 256)
[1] "b493d48364afe44d11c0165cf470a4164d1e2609911ef998be868d46ade3de4e"
> md4("banana")
[1] "f1fbbfb6277cbf01e27d61238a72491a"
> md5("banana")
[1] "72b302bf297a228a75730123efef7c41"
> blake2b("banana")
[1] "d4afa3130126ddcc01bb49e1388b0fbc94c185d1a07a67046a5b66923c38e178f490bc9b91a7e41c2d670be3c8435e5914b5cb5ee0d0ff52d9a783f601b18794"
> blake2s("banana")
[1] "228c3a8526197e63044a1654a9407707d7e250a7ccac489d3cad024ce6cd9ad7"
> ripemd160("banana")
[1] "e8f92e55b15aec83f458cfee39dd4ffeb7f4b8ed"

Pythonの場合

デフォルトでhashlibというメソッドがあるので、これを利用します。

hasulibメソッドにある各ハッシュ関数に対応するモジュールを次のような形で使ってやれば、ハッシュ値が出力されます。

>>> import hashlib
>>> PW="banana"
>>> print("MD5のハッシュ値:", hashlib.md5(PW.encode("utf-8")).hexdigest() )
MD5のハッシュ値: 72b302bf297a228a75730123efef7c41
>>> print("sha384のハッシュ値:", hashlib.sha384(PW.encode("utf-8")).hexdigest() )
sha384のハッシュ値: 92f7818b31b9936b90a5178e811979ef3ba68a14b57e8362424d54446f31ad2a249e4306628ad33ccb28b3e9dc5e043e
>>> print("sha1のハッシュ値:", hashlib.sha1(PW.encode("utf-8")).hexdigest() )
sha1のハッシュ値: 250e77f12a5ab6972a0895d290c4792f0a326ea8
>>> print("sha224のハッシュ値:", hashlib.sha224(PW.encode("utf-8")).hexdigest() )
sha224のハッシュ値: 8f5901a4a0a2d72ff9882e63c08d4c32b3eaa3683b6e5bfc0ca03e86
>>> print("sha256のハッシュ値:", hashlib.sha256(PW.encode("utf-8")).hexdigest() )
sha256のハッシュ値: b493d48364afe44d11c0165cf470a4164d1e2609911ef998be868d46ade3de4e
>>> print("sha512のハッシュ値:", hashlib.sha512(PW.encode("utf-8")).hexdigest() )

こんな感じでRやPython等でも簡単に出力することが出来ます。

【初心者向け】これからpython記事書いてきます。皆さんpython始めませんか。

少し前に、pythonについて書くようお達しを受けたので、とりあえずpython関連の記事も書いていこうと思います。

このブログ、分析は基本的にRで行っているんですけど、記事自体はどうやらpythonの方が需要あるみたいです。やっぱり最近話題だからですかねー。


ところで今回の記事ですが、pythonについて書いていきますが、pythonの入門の入門程度の内容から記事にしていくと非常にしんどいので、
その辺ははじめに参考図書をあげるにとどめておこうと思います。

昔私がpythonを始めるにあたってTwitter経由で、フォロワーのパイソニスタ(pythonに熟練した人のこと)の方々に参考図書を散々聞いて回ったので、結構良書を紹介できると思います。

是非これを機会に皆さんもpython導入してみてください!笑


pythonの入門本

【プログラミング未経験の方向け】
pythonスタートブック

多分これ以上簡単な入門本はないんじゃないかというくらい、読みやすいpythonの入門書です。私もpythonを触り始めた当初はプログラミング未経験でしたので、この本は非常に参考になりました。



・プログラミング超初心者が初心者になるためのPython入門1~3



内容も良いのですが、この本は安いのが良いですね。なんとkindleだと無料で読めるみたいですね。タダ同然でpythonの入門が出来る優れものです。


・いちばんやさしい Python入門教室

こちらもかなりわかりやすい入門書です。私は使いませんでしたが、評価も高く、わかりやすいと評判です。





【脱プログラミング入門した人向け(R含む他の言語をいじったことのある人も対象)】
・入門python3

私がスタートブックの後に読んだ本です。かなり丁寧にpythonの基本操作や概念についての説明が書いてあります。この本に従って実際にコードを打ち込んでいれば自然とpythonの感覚が身についている事間違いなしです。



それでは、Numpyの記事に戻ります。



Numpyとは

pythonでベクトル計算や行列計算をする際に簡単かつ高速に行えるというパッケージです。データ分析では結構必須だったりします。

ndarray型という特殊な型を使って大規模計算を行うことが出来ます。

ndarray型の生成

とりあえず、物は試しで色々な方法でベクトルや行列を生成していきます。

とりあえずNumpyを読み込んでおきます。

import numpy as np

別にnpと名前を付ける必要は無いのですが、所謂界隈のしきたりというか、そういうやつです。まあ実際イチイチnumpyと打つのも面倒くさいので短い名前を付けておくといいと思います。

array関数

array関数にリストやタプルを突っ込むことでndarrayを作ることが出来ます。

#数字が入ったリストを作成
data=[5,3,5.6,1]

#dataをarray関数で変換
arr=array(data)
print(arr)
#出力結果
array([5. , 3. , 5.6, 1. ])

これ、要は5,3,5.6,1が並んだベクトルだと思ってくれれば大体大丈夫です。


複数重ねればベクトルも作れます。

data2=[[3,2,1],[1,2,3]]
arr=np.array(data2)
print(arr)
[[3 2 1]
 [1 2 3]]


タプルでもいけます。

data3=(5,4,3)
arr3=np.array(data3)
print(arr3)
[5,4,3]
arange関数

考え方は元々pythonに備わっているrange関数と同じです。
使ってみるが早しということで、使って出力を見てみます。

np.arange(10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
zeros関数とones関数

zeros関数で0のみの配列、ones関数で1のみの配列が作れます。

np.zeros(11)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
np.ones((11,3))
array([[1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.],
       [1., 1., 1.]])
empty関数

タプルで次元を指定してやると適当な値の配列を生成してくれます。

np.empty((2,2))
array([[5. , 3. ],
       [5.6, 1. ]])
np.empty((3,3))
array([[3.44788773e-074, 6.45331734e-074, 3.69649234e+177],
       [5.59238927e-076, 1.61024732e-075, 1.06059841e-074],
       [1.96353574e-077, 8.34402697e-308, 3.91792476e-317]])
eye関数

単位行列を生成する関数です。

np.eye(5,5)
array([[1., 0., 0., 0., 0.],
       [0., 1., 0., 0., 0.],
       [0., 0., 1., 0., 0.],
       [0., 0., 0., 1., 0.],
       [0., 0., 0., 0., 1.]])

行列計算

このように生成したndarray型データを行列を扱うかのように簡単に計算することが出来ます。
足し算引き算掛け算割り算等々はまあ+とか-とか*とか/を使えば良くて、直感的に分かりやすいので省略します。


まず、行列を転置してみます。これは.Tとつけるだけで転置できます。

data3=[[3,2,1],[1,2,3],[5,9,7]]
arr3=np.array(data3)
print(arr3)
[[3 2 1]
 [1 2 3]
 [5 9 7]]
#転置してみる
print(arr3.T)
[[3 1 5]
 [2 2 9]
 [1 3 7]]


行列の内積計算はdot関数によって行うことが出来ます。

np.dot(arr3,arr3.T)
array([[ 14,  10,  40],
       [ 10,  14,  44],
       [ 40,  44, 155]])


他にも要素について対数をとったり、指数関数や三角関数で変換したり、ルートをとったりなどなど色々出来たりします。


大規模データを扱ったりする場合は、このNumpyを活用していかないと、スピードがまるで変ってきますので、使ったことの無い方は導入してみることをおすすめします。