4 minutes
Pandasの基本操作まとめ
備忘録的メモ
この記事は Python 環境がなくても、Google Colab
上で実際に動かすことができます。
実行環境
! cat /etc/issue
Ubuntu 18.04.3 LTS \n \l
! python -V
Python 3.6.9
! pip show pandas | grep -e Name -e Version
Name: pandas
Version: 1.0.3
ソースコード
ソースコードの実行には Google アカウントが必要です。
また実行時 警告: このノートブックは Google が作成したものではありません。
とポップアップが出ます。データや認証情報の読み取りが無いよう留意しておりますが、実行に際しては一度ソースコードを読んでから実行することをお願い申し上げます。
Pandas とは
データ操作と分析のための Python ライブラリ
Excel のような 2 次元のテーブルを用いて構造化されたデータへのアクセスを行う。
csv, json, xlsx などに対応していて, インターネット上のソースファイルも利用できる
データセットのダウンロード
今回は Titanic データセットを利用します。
https://www.openml.org/d/40945
Unix コマンドを用いてデータセットのダウンロードと簡単な中身の確認をしていきます。
curl -o titanic.csv https://www.openml.org/data/get_csv/16826755/phpMYEkMl
内容確認
head -n 3 titanic.csv && tail -n 3 titanic.csv
"pclass","survived","name","sex","age","sibsp","parch","ticket","fare","cabin","embarked","boat","body","home.dest"
1,1,"Allen, Miss. Elisabeth Walton","female",29,0,0,"24160",211.3375,"B5","S","2",?,"St Louis, MO"
1,1,"Allison, Master. Hudson Trevor","male",0.9167,1,2,"113781",151.55,"C22 C26","S","11",?,"Montreal, PQ / Chesterville, ON"
3,0,"Zakarian, Mr. Mapriededer","male",26.5,0,0,"2656",7.225,?,"C",?,304,?
3,0,"Zakarian, Mr. Ortin","male",27,0,0,"2670",7.225,?,"C",?,?,?
3,0,"Zimmerman, Mr. Leo","male",29,0,0,"315082",7.875,?,"S",?,?,?
行数確認
cat titanic.csv | wc -l
1310
pandas の inport
import pandas as pd
# バージョン確認
pd.__version__ #> '1.0.3'
データのインポート
src = "titanic.csv"
df = pd.read_csv(src)
データソースがjson
の場合pd.read_json(src)
, excel
の場合pd.read_excel(src)
のように直感的に読み込むことができます。
データソースがインターネット上にある場合(例えば
COVID-19 )もraw
ファイルを指定してあげることで同様に読み込むことができます。
src = "https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv"
内容の確認
頭 5 行の表示
df.head(5)
うしろ 5 行の表示
df.tail(5)
カラムを表示
df.columns
インデックスを表示
df.index
値を表示
df.values
各カラムのタイプを表示
df.dtypes
pclass int64
survived int64
name object
sex object
age object
sibsp int64
parch int64
ticket object
fare object
cabin object
embarked object
boat object
body object
home.dest object
dtype: object
さらに詳しい DataFrame の基本情報を表示
df.info()
RangeIndex: 1309 entries, 0 to 1308
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 pclass 1309 non-null int64
1 survived 1309 non-null int64
2 name 1309 non-null object
3 sex 1309 non-null object
4 age 1309 non-null object
5 sibsp 1309 non-null int64
6 parch 1309 non-null int64
7 ticket 1309 non-null object
8 fare 1309 non-null object
9 cabin 1309 non-null object
10 embarked 1309 non-null object
11 boat 1309 non-null object
12 body 1309 non-null object
13 home.dest 1309 non-null object
dtypes: int64(4), object(10)
memory usage: 143.3+ KB
基本統計
基本統計の表示
df.describe()
全てのカラムにおける統計の表示
df.describe(include="all")
行列の抽出
行の抽出
df.loc[:, 'pclass']
# 以下のコードで同様の結果を得る
df.pclass
df["pclass"]
0 1
1 1
2 1
3 1
4 1
..
1304 3
1305 3
1306 3
1307 3
1308 3
Name: pclass, Length: 1309, dtype: int64
列の抽出
df.loc[0]
pclass 1
survived 1
name Allen, Miss. Elisabeth Walton
sex female
age 29
sibsp 0
parch 0
ticket 24160
fare 211.3375
cabin B5
embarked S
boat 2
body ?
home.dest St Louis, MO
Name: 0, dtype: object
特定の行列の抽出
行番号(index)が 100 から 104 の"pclass”, “age"のカラム
df.loc[range(100,105), ["pclass", "age"]]
単独要素の抜き出し
df.at[1000, "ticket"]
'367228'
loc
でも同様の結果を得るが、at
の方が速い
%%timeit
df.loc[1000, "ticket"]
The slowest run took 14.63 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 7.47 µs per loop
%%timeit
df.at[1000, "ticket"]
The slowest run took 15.20 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 4.26 µs per loop
複雑な抽出
survived
カラムが 1
である列
df[df["survived"] == 1]
df.query('survived == 1')
embarked
カラムが C
or S
である列
df[df["embarked"].isin(["C", "S"])]
df.query('embarked in ["C", "S"]')
name
が A
で始まる列
df[df["name"].str.startswith("A")]
name
が e
で終わる列
df[df["name"].str.endswith("e")]
name
に z
が含まれる列
df[df["name"].str.contains("z")]
name
に 別称(()
で囲まれた名前)が含まれる列
df[df["name"].str.match("._\([^\)]_\).\*")]
dtype の変更
age
カラムは int
もしくは float
で表されて欲しいが、現状 Object
で認識されている
df["age"].dtype #> dtype('O')
age
カラムで数値以外の文字が含まれるものを抽出してみると、?
が含まれることがわかった。
set(df[df["age"].str.match("[^\d]")]["age"]) #> {'?'}
なので?
をNaN
に変更してやれば、float
への変換ができる。
# 数値以外の文字列をNaNで置換
df["age"] = df["age"].replace({'?': 'NaN'})
# dtypeの変更
df["age"] = df["age"].astype(float)
以下のようmask
や where
を使う手もある
df["age"] = df["age"].mask(df["age"].str.match("[^\d]"))
df["age"] = df["age"].where(df["age"].str.match("\d"))
欠損地の扱い
?
を NaN
に置換して、float
データとして扱わせる為、NaN
は欠損値として扱われることになる。
欠損値でないものの数
df["age"].count().sum() #> 1046
欠損値の数
df["age"].isnull().sum() #> 263
欠損値がある行の表示
df[df['age'].isnull()]
欠損値を持つ行の削除 dropna()
len(df.copy().dropna().index) #> 1046
欠損値を持つ列の削除 dropna(axis=1)
len(df.copy().dropna(axis=1).columns) #> 13
欠損値を 0 で置換 fillna(0)
df.fillna(0).at[15,"age"] #> 0.0
欠損値を平均値で置換 df.fillna(df.mean())
df.fillna(df.mean()).at[15,"age"] #> 29.8811345124283
中央値 median()
最頻値 mode()
欠損値を前の値で置換 df.fillna(method='ffill')
df.fillna(method='ffill').loc[[14, 15, 16]]
欠損値を後ろの値で置換 `df.fillna(method='bfill')`
```python
df.fillna(method='bfill').loc[[14, 15, 16]]
文字一括置換 (2020/6/12 追記)
df.apply(lambda x: x.str.translate(str.maketrans({',': '', '%':'', 'K': ''})))
文字列を含む数値型のキャストで使える
df.apply(lambda x: x.str.translate(str.maketrans({',': '', '%':'', 'K': ''}))).astype(np.float)