サムネイルで描いた事がこのエントリーの全てです.
Pythonでは、「pandas」というライブラリを使ってデータ分析や解析をすることが非常に多いです.
でも、「利用方法(またはユースケース)」に合わせた入門ってあんまりない気がします.
ということで、「PyCon mini Sapporo 2019」でそんな話をしてきました.
訳あって資料およびJupyter notebookは非公開*1ですが、こちらにその基本とかをまとめます.
TL;DR - このエントリーは
- 実務や趣味のデータ分析でpandasを使う例を紹介します.
- 初歩的な使い方から中級者になるまでのヒントになると思います.
- なお,統計テクニック・機械学習には触れません・やりません.
なお、対象読者は「そこそこPythonとJupyter notebookが使えてこれからデータ分析・解析をやる」方となります.*2
参考文献
今回まとめるにあたって参考にした書籍・ブログです.
Pythonによるデータ分析入門 第2版 ―NumPy、pandasを使ったデータ処理
- 作者:Wes McKinney
- 発売日: 2018/07/26
- メディア: 単行本(ソフトカバー)
もくじ
pandasのきほん
そもそもpandasってなーに?
pandas #とは
- 公式サイト(https://pandas.pydata.org/)曰く、「Python Data Analysis Library」
- Pythonでデータ分析するために使うものが一通り揃っているライブラリ.
- Pythonでデータ分析・解析を行う人がほぼ使う、デファクトスタンダードな道具.
使いみち
- データの入出力(CSV, Excel, DB, HTML, etc...)
- データの前処理(データの抽出,欠損値処理,ピボットテーブルしたりetc...)
- 簡易的な可視化(グラフを書いてimageとして保存,など)
機械学習, 統計そして「実務」「趣味」にも活かせる神ライブラリである!
このエントリーでやること
例えば、こういったお仕事・分析があったとします.
- システムやアプリのデータをかき集めてレポートにまとめて偉い人に説明する.
- 「データをかき集めてExcelにして提出」するのがわたし
- 「パワポとか書いて説明する」のが先輩とか上司.
- データはCSVに生ログ、SQLとか色々、基本的には汚いデータが多いです.
この、「色んなデータ」を読み込んで「Excelにする」までをこのエントリーでやってみます.
本来は色んなデータを読み込んでやるべきですが、説明が煩雑になるので、
CSVを読み込んで加工してExcelにする
をゴールとします(html他の入力方法は少しだけ説明します.)
こんにちはpandas - 導入編
事前条件
- PCはMacでもWindowsでもLinuxでもかまいません.
- Python
3.43.6*3以上、原則として最新版(現時点では3.7)がいいでしょう. - pipで導入します. Anacondaの方はいい感じに読み替えてやってください.*4
1. 仮想環境を準備
$ python3 -m venv ~/python_venv/pandas_nyumon $ source ~/python_venv/pandas_nyumon/bin/activate
2. 必要なライブラリを入れる
基本のライブラリ
(pandas_nyumon)$ pip install pandas jupyter matplotlib
今回はExcelも使うのでこちらも
(pandas_nyumon)$ pip install openpyxl xlrd
3. 動くかどうかチェック
notebookが動けばOK
(pandas_nyumon)$ jupyter notebook
ここまで来たら実際に使ってみましょう.
pandasを使おう
一番基本的な利用シーンに合わせて紹介します.
pandasのデータの種類(大雑把)
二次元データ(Dataframe)と一次元データ(Series)の二種類ある.
Dataframe #とは
複数カラム存在する行列データ
import pandas as pd # Dataframeはこれ df_yakiu = pd.DataFrame({'Kamome': [10, 10, 10, 3], 'Tiger': [1, 0, 1, 2]})
Dataframeは色々なふるまいができます.
例えば足し算あっ(察し*5
Series #とは
単一カラムのデータを指します.
s = pd.Series(['四球', '四球', '四球', '四球', '本塁打', '三振', '三振', '三振'])
これも色んなふるまいができます.*6
初級編 - データと友達になる
まずはデータと友達になろう.
今回のデータは
- Kaggleで使われている、MLBの公開データ を使います.
- People.csv(選手マスタ), Batting.csv(打撃成績)を使って,
- 色んな指標(例:打率、OPS)を計算してみましょう.
???「メジャーリーグ興味ないンゴ」と言わずにどうぞお付き合いください :bow:
pandasでCSVを読み込む
pd.read_csvで読み込んでDataframeを作ります
# インポートしましょう(慣習で, alias(as)はpd) import pandas as pd # やってみよう(選手ごとの打撃結果) df = pd.read_csv('./{任意のパス}/Batting.csv')
CSV以外のデータは?
大体のデータはread_なんとかで読めます, たくさんあるので色々試すといいかも*7
# Excel(Excelデータを読み込む) df = pd.read_excel('./datasets/hoge.xlsx') # sql(select文の結果からDataframeを作る, 事前にSQLAlchemyやコネクタの設定必要) df = pd.read_sql('select id, name from users where name like "Arai%"') # html(指定したURLのtableタグをParseしてDataframe作る,いわばスクレイピング) df = pd.read_html('https://example.com/tsubakuro/index.html')
計算してみよう
Dataframeは「行列」なので、行列同士の演算ができます.
例えば、読み込んだデータが「Batting(打撃成績)」の場合、打率はこのようにして計算ができます.
# 打率を計算してみよう. 打率(BA)は 「安打数(H) ÷ 打数(AB)」 df['BA'] = df['H'] / df['AB']
この調子で、
- 出塁率
- 長打率
- OPS
なども計算できます、興味ある方はぜひやってみてください.*8
別のデータを紐付ける
例えば今は打撃のデータのみ読み込んでいますが、こちらには「選手ID」があっても「選手名」がありません.
選手の名前を取るためには別のデータ(People.csv)を読み込んで、紐づけする必要があります.
SQL的な解法だと、「join」を使うことになると思いますが、欲しいのは選手名だけなのでシンプルに「成績データ」に「選手名」をタグ付けしてみましょう.
# まずは選手マスタを読みこんでみよう df_people = pd.read_csv('./{任意のパス}/People.csv') # 名前とindexを設定 df_people['name'] = df_people['nameFirst'] + ' ' + df_people['nameLast'] # playerIDがuniqueなのでこちらをkeyに df_people.set_index('playerID', inplace=True) # いよいよ名前を設定!ひとまずfor文で回してセット!(もっといい方法は中級編にて) for i, row in df.iterrows(): try: name = df_people.loc[row.playerID]['name'] except KeyError: print('Warning', row.playerID) name = 'Nanashi-San' df.at[i, 'player_name'] = name
エレガントな方法は後ほど紹介しますが、最初は「データの素性」を見ながら愚直にforで回して良いと思います、Excelで開けるサイズなら.*9
必要なデータだけ取得する
Excelで言うところのフィルター、SQLで言うところのSELECTです.
さっきのDataframe(すでに選手名付き)から大谷翔平(Shohei Ohtani)さんだけ欲しい場合は、
df.query('player_name == "Shohei Ohtani"')
これで事足ります.
なお、この例はqueryですがwhereなど他の方法もあります.
結果をExcelに出力
to_excelで一発です.
# 結果をExcelに出力する df.to_excel('mlb_batting_stats.xlsx')
これぐらい使えるようになると、普段仕事でまずは使おう!って気になると思います、ぜひお試しあれ!
中級編 - エレガントな書き方
いくつかテクニックありますが、「初級」で触れたfor文の話題を.
for文を使わないやりかた
例えば先程出てきたこちら.
# いよいよ名前を設定!ひとまずfor文で回してセット!(もっといい方法は中級編にて) for i, row in df.iterrows(): try: name = df_people.loc[row.playerID]['name'] except KeyError: print('Warning', row.playerID) name = 'Nanashi-San' df.at[i, 'player_name'] = name
Dataframe(df)が数百〜数千行であればいいのですが、これが数十万数百万行あっても同じことするか!?
って言われたらしないですよねと.
pandasの内部処理的に行列処理する方法があって、その方法で書くとこのように書き換えができます.
# Seriesのmap関数を使います. def get_player_name(playerID: str) -> str: try: name = df_people.loc[row.playerID]['name'] except KeyError: name = 'Nanashi-San' return name df['player_name'] = df['playerID'].map(get_player_name)
なぜこれが良いか?は以前こちらのエントリーに上げていますのでご興味ありましたらぜひ.
指定した列データのみ読み込む
read_csvやread_excelだと、デフォルトはすべての列を読み込みます.
カラム数が100を超えるようなデータだったりするときはホントに使うデータだけを指定するだけでもメモリ等のリソースに優しくてオススメです.
# これだと全部読んじゃう df_people = pd.read_csv('./{任意のパス}/People.csv') # 使うものだけ読みたいときはこれ COLUMS = ('playerID', 'nameFirst', 'nameLast') df_people = pd.read_csv('./{任意のパス}/People.csv', usecols=COLUMS)
これもやった方がいい理由・背景は上記と同じエントリーにありますので気になる方はぜひ.
さあやってみよう!
ということで、お仕事なり学業なり趣味で是非とも試してやってみてください!
書籍やサンプルデータという観点ではやはりJupyter notebook本がやりやすい*10と思いますので写経などからはじめてみては如何でしょうか?
データ分析の楽しさがこれで伝わると幸いです!
*1:理由はいろいろとありますが、今回はブログの方がわかりやすく伝わるかなと思い、ブログにしました.それが最大の理由.
*2:のでJupyterの導入・Pythonの基本文法はすっ飛ばします
*3:3.4はもうEOLだし他ももうすぐ...っていうコメントをいただいたので、3.6にしました
*4:このサンプルをvenv + pipでやったのでそれに従い説明します.Anacondaでも普通に動きます(一応試した)
*5:なんでやHANSHIN関係ないやろ
*6:この例、なんJ民なら伝わるやろ(震え
*7:ちなみにread_htmlは過去にこちらのエントリーでやってます&スクレイピングを伴うので自己責任で行ってください.
*8:発表では例を示しましたがここではあえてクイズにします、正解者に何かあるかもしれない(適当)
*9:最初から難しく書いたりエレガントにしようとするとかえってミスするのでオススメできません、全部データを読まなくても最初の数行をheadでとりながらやってもいいかと思います.
*10:Jupyter, pandas, matplotlibを一通り覚えるならこれがホントやりやすい.ただし、(不幸にも出版時期の関係で)Bokehの記法が古いやつなのでそこだけ注意必要かも.