データ分析ガチ勉強アドベントカレンダー4日目。 今日はpandas
を取り扱う。
機械学習系の本にも、numpy、scipy, matplotlibの使い方は載っていても、pandasを載せている本って意外と少ない。 けれど、実際numpyの次くらいによく使う。データを取り扱ったり、計算したりするときにとても便利。一方で、癖があって慣れるまでに時間がかかる。なので、基礎的な事項をまとめておこうと思う。
今回も、githubにコードや扱うデータを配置している。
都道府県の重心データを使いながら、pandasのお勉強をしようという試みである。
pandasとは
配列データの取扱が便利に行える
- データの取り出し
- データの操作
- 統計計算
- 時系列データの処理
などを簡単に行えるため、重宝する。
基礎事項は、公式ページの10 minutes to pandasを参考にすると良い。しかしこれ、確実に10分で終わらない内容となっている。その分濃いのでまあOKとする。
また、リファレンスとしては下記の本も有用である。pandasの製作者が作っているので、信頼性は高い。
Pythonによるデータ分析入門 ―NumPy、pandasを使ったデータ処理
- 作者: Wes McKinney,小林儀匡,鈴木宏尚,瀬戸山雅人,滝口開資,野上大介
- 出版社/メーカー: オライリージャパン
- 発売日: 2013/12/26
- メディア: 大型本
- この商品を含むブログ (19件) を見る
基本事項
データの読み込み/書き込み
pandasの使い所としては、自分でデータ配列を作るよりかは、読み込んだcsv等のファイルを取り扱う時のほうが多いので、まずはソレ。pythonの組み込み関数であるcsv
を使ってもいいが、pandasのほうがより手軽である。
# 読み込み(csv) df = pd.read_csv("japan.csv", index_col="prefecrue") # 書き込み(csv) df.to_csv("japan2.csv")
index_col
は、インデックスにしたい列のこと。行の指定をするときに最もわかりやすいモノ(専門的に言えば主キーのようなもの?)を指定する。指定しなければ通し番号になる。
Tips : データの文字コードがアレだと、下記のようなエラーが出るときもある。
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8e in position 0: invalid start byte
そういうときは、
df = pd.read_csv("japan.csv", encoding="shift-jis")
とすると、解決する
SeriesとDataFrameの作成
読み込んでしまうと、そのまま表がDataFrameとして保管されるが、時には自ら作る場合もあるだろう。 pandasで用意されているデータ構造は下記のようなものがある。
種類 | 特徴 |
---|---|
Series |
1次元配列。要素をindexに保管 |
DataFrame |
2次元配列。行をindex、列をcolumnとして保存する |
Panel |
3次元配列 参考 |
正直、SeriesとDataFrameだけで良い。Panelは初めて知った。
下記が、データフレームの作り方である
# seriesが1次元配列、dataframeが多次元配列 se = pd.Series([1,3,5,np.nan,6,8]) print(se) # dataframe dates = pd.date_range("20130101",periods=6) df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
indexは指定しなければ、通し番号になる。datetimeなどで指定してやると後々時刻の範囲検索などもできるので便利である。
データの基本的な情報をGetする
(基本的にDataFrameの話を中心にすすめる)
こうしてGETしたDataFrameの、基本的な情報は、下記のようにしてアクセスできる
df.head(3)
# 初めの3つを見るdf.tail(3))
# 後の3つを見るdf.index
# インデックスを確認df.columns
# カラムを表示df.values
# 中の値をarray形式で表示df.describe()
# 統計量(頻度、uniqueな値の個数、max,min,平均、25%点etc...)を表示
df.values
までは、は中身を見るのにどれもよく使う。describe
は初めて知った。便利そうだから今後使ってみる。
データ内部へのアクセス
DataFrame型へのアクセスは、様々用意されている。が、様々用意されているが故に、どれがどのようなアクセスの仕方だったのか、わかりにくくなっているのも事実である。ここで、どういうアクセスの仕方が可能なのか、まとめておく。
- 基本
df["longtitude
] # カラムの値(df.longtitude
でも可能)df[0:3]
# indexの指定- ラベルで指定 :
df.loc
df.loc["東京都"]
# indexの指定df.loc[:,["longtitude","latitude"]]
# columnのみ指定df.loc["東京都",["longtitude","latitude"]]
#両方指定df.loc["東京都","longtitude"]
# セル一つ分の指定df.at["東京都","longtitude"]
# セル一つ分の指定(より高速なアクセスが可能)- 位置による指定 ;
df.iloc
df.iloc[3]
# ilocによる行指定df.iloc[3:5, 0:2]
# ilocによる行列範囲指定df.iat[1,1]
# scalarの値(高速版)- 条件検索
df = df[(df.index!="沖縄県")&(df.index!="北海道")]
# 沖縄と北海道は除外- 数値的な条件(>, == など)も可能
新しいcolumnの追加、計算の適用。
japanデータは、緯度経度が136:08:07
のように、数値で入っていない。なので、この60度法で書かれたものをfloat型に変換し、新しいcolumnを追加したい。columnの追加は以下のような方法で出来る。辞書の追加のようなものだ。
df["new_column"] = (新しい配列 or Series)
変数の変換には、calc_number
という関数を用意した。
def calc_number(d_num): """ 度であらわされてるのを、小数に変換 """ d = d_num.split(":") n = int(d[0])+float(d[1])/60+float(d[2])/3600 return n
さて、問題は、これをlongtitude,latitude関数の全てのindexに適用させるにはどうしたら良いかだ。 方法は2つある。
- 一度配列を作り直して、新しいcolumnとして追加する
- apply関数を適用する
二番目の方法のほうが、シンプル。apply関数をつかうと、指定したcolumn全体に所与の関数を適用してくれる。
さっきのcalc_number
関数を適用する
df["latitude_num"]=df.latitude.apply(calc_number) df["longtitude_num"]=df.longtitude.apply(calc_number) print(df[df["latitude_num"]>135].index)
出力
Index(['山梨県', '静岡県', '長野県', '岐阜県', '富山県', '新潟県', '石川県', '栃木県', '群馬県', '埼玉県', '福島県', '北海道', '山形県', '福井県', '岩手県', '東京都', '奈良県', '宮城県', '秋田県', '三重県', '神奈川県', '青森県', '愛知県', '和歌山県', '滋賀県', '大阪府', '茨城県', '京都府', '千葉県'],
ちゃんと西の方にある県が取り出せているよう。
イテレーションを回す
pandasはイテレーション用のメソッドを持っている。 が、なんかややこしいのでなかなか覚えられない。コチラのサイトを無限回見ている。何度もググって何度もこのページを開くのも流石にアレなので、ここにメモしておく。
DataFrameなら、下記の3種類のイテレーション方法がある
(StatsFragmentsより引用)
イテレーションの練習に、各都道府県の重心をプロットしてみる。*1
plt.figure(figsize=(8,8)) for key, row in df.loc[:,["longtitude_num","latitude_num"]].iterrows(): plt.scatter(row["latitude_num"],row["longtitude_num"], marker="x",color="blue")
日本地図っぽい点群が出てきた。
統計計算をしてみる
今回の最後に、統計計算をpandasでしてみる。 pandasでは、簡単に統計計算を行うことが出来る。例えば以下の様なものが用意されている
df.mean()
: 平均df.std()
: 標準偏差df.var()
: 分散df.min()
: 最小値df.max()
: 最大値
全国の緯度と経度の平均を取ってみて、先程の都道府県重心プロットに重ね合わせる。どこになると思います?予想してみてください。
longtitude_mean = df["longtitude_num"].mean() latitude_mean = df["latitude_num"].mean() print("latitude;{:.2f}, longtitude_mean:{:.2f}".format(latitude_mean, longtitude_mean)) # >>> latitude;136.01, longtitude_mean:35.34
さっきの日本地図に重ね合わせると
こんな感じ。値をgooglemapで確認すると...
滋賀県に!
まとめ
というわけで、よく使ったり調べたりする事柄を、まとめておいた。*2 しかし、ここに載せているのはpandasの機能のほんの一部分に過ぎない。 もともと金融データを取り扱う用に作られている*3ため、特に時系列データの取扱いは得意なようである*4。そのあたりもどこかでまとめられたらまとめる。
明日はjupyter!!