環境設定
開発環境
OS |
MacOS Mojave 10.14.5 |
Jupyter Notebook |
6.0.3 |
conda |
4.8.3 |
Python |
3.6.10 |
pandas |
1.0.3 |
NumPy |
1.18.1 |
モジュールのインポート
基本モジュールのインポート
import pandas as pd
import numpy as np
便利なコマンド集
逆引き |
コマンド |
常に全カラム表示 |
pd.set_option('display.max_columns', None) |
pandasのバージョンを表示 |
pd.__version__ |
NumPyのバージョンを表示 |
np.__version__ |
依存パッケージなどの詳細情報を表示 |
pd.show_versions(as_json=False) |
Jupyter Notebook
逆引き |
コマンド |
Jupyter Notebookを起動 |
$ jupyter notebook |
Jupyterの諸々のバージョンを確認 |
$ jupyter --version |
Anacondaをアップデート |
$ sudo conda update anaconda |
JupyterのPythonをアップデート(3.6.8→3.6.10) |
$ conda update python |
Jupyterのモジュール全てをアップデート |
$ conda update --all |
Jupyterのモジュールを個別にアップデート(pandas) |
$ conda update pandas |
ショートカットキー
コマンドモード(Mac OS)
逆引き |
コマンド |
編集モード |
Enter |
セルを実行 |
Control +Enter |
セルを実行し、下のセルに移動 |
Shift +Enter |
上のセルを選択する |
K |
↑ |
下のセルを選択する |
J |
↓ |
セルをコピー |
C |
セルを切り取り |
X |
下に貼り付け |
V |
保存 |
S |
Command +S |
上にセルを追加する |
A |
下にセルを追加する |
B |
セルを削除する |
D +D |
セルの削除をやり直す |
Z |
検索と置換 |
F |
上にスクロール |
Shift +Space |
下にスクロール |
Space |
コードセルにする |
Y |
マークダウンセルにする |
M |
ショートカットキーの一覧を表示 |
H |
編集モード(Mac OS)
逆引き |
コマンド |
コマンドモード(編集モードを解除) |
Esc |
インデント |
Tab |
Command +] |
アンインデント(逆インデント) |
Shiht +Tab |
Command +[ |
コメントアウト |
Command +/ |
コード補完 |
Tab |
ツールチップを表示 |
Shift +Tab |
セルを保存 |
Command +S |
セルを実行 |
Control +Enter |
セルを実行し、下のセルに移動 |
Shift +Enter |
マジックコマンド
逆引き |
コマンド |
Jupyter Notebook内にmatplotlibを描画 |
%matplotlib inline |
.ipyrbファイルのディレクトリを確認 |
%pwd |
セルの実行時間を1回計測 |
%%time |
セルの実行時間を複数回計測 |
%%timeit |
その他のJupyter Notebookの便利設定はこちらのリンクに丁寧にまとめてありました。
参考
Jupyter 知っておくと少し便利なTIPS集Qiita
データ構造
pandas.Series
シリーズは1次元配列のようなオブジェクトです。シリーズには連続したデータ値とそれに関連付けられたインデックスというデータラベルの2つの配列が含まれています。
シリーズを作成
s = pd.Series(data=[295, 201, 7])
print(s.to_markdown())
# | | 0 |
# |---:|----:|
# | 0 | 295 |
# | 1 | 201 |
# | 2 | 7 |
注意
pandas.Series.to_markdownメソッドやpandas.DataFrame.to_markdownメソッドは、pandasのバージョンが1系だと使うことができます。
コンソールに出力されているシリーズの文字列表現では、インデックスが左側、データ値が右側に表示されます。この例では、データに対するインデックスを指定していなかったので、0からN-1までのデフォルトのインデックスが割り当てられています。
シリーズのvalues
属性とindex
属性を使うと、データ配列とインデックスをそれぞれ取得することができます。
print(s.values)
# array([295, 201, 7])
print(s.index)
# RangeIndex(start=0, stop=3, step=1)
# range(3)と等しい
各データを特定するためにインデックス付きのシリーズの方が好ましい場合もあります。
インデックス付きのシリーズを作成
s = pd.Series(data=[295, 201, 7], index=['apple', 'banana', 'cherry'])
print(s.to_markdown())
# | | 0 |
# |:-------|----:|
# | apple | 295 |
# | banana | 201 |
# | cherry | 7 |
print(s.index)
# Index(['apple', 'banana', 'cherry'], dtype='object')
インデックス付きのシリーズは辞書からも作成することができ、シリーズをインデックスとデータ値がマッピングされた固定長の順序付きとして扱うことができます。
インデックス付きのシリーズを辞書から作成
s = pd.Series(data={'apple': 295, 'banana': 201, 'cherry': 7}))
print(s.to_markdown())
# | | 0 |
# |:-------|----:|
# | apple | 295 |
# | banana | 201 |
# | cherry | 7 |
print('apple' in s)
# True
print('dorian' in s)
# False
for index, (key, value) in enumerate(s.items()):
print(index, key, value)
# 0 apple 295
# 1 banana 201
# 2 cherry 7
シリーズのデータ配列の各要素には、リストまたは辞書のようにアクセスすることができます。
シリーズの各要素にアクセス
print(s['banana'])
# 201
print(s[-1])
# 7
print(s[0:2].to_markdown())
# | | 0 |
# |:-------|----:|
# | apple | 295 |
# | banana | 201 |
print(s[['apple', 'cherry']].to_markdown())
# | | 0 |
# |:-------|----:|
# | apple | 295 |
# | cherry | 7 |
print(s[[False, True, True]].to_markdown())
# | | 0 |
# |:-------|----:|
# | banana | 201 |
# | cherry | 7 |
他にもシリーズに対して、条件指定によるフィルタリングやスカラー値の演算、数学的な関数を行うことができます。
シリーズの操作
print(s[s>100].to_markdown())
# | | 0 |
# |:-------|----:|
# | apple | 295 |
# | banana | 201 |
print((s*3).to_markdown())
# | | 0 |
# |:-------|----:|
# | apple | 885 |
# | banana | 603 |
# | cherry | 21 |
print(np.sqrt(s).to_markdown())
# | | 0 |
# |:-------|---------:|
# | apple | 17.1756 |
# | banana | 14.1774 |
# | cherry | 2.64575 |
また、シリーズのデータ配列とインデックスはそれぞれname
属性を持ちます。
name属性に値を代入
s.name = 'weight'
s.index.name = 'fruits'
print(s.to_markdown())
# | fruits | weight |
# |:---------|---------:|
# | apple | 295 |
# | banana | 201 |
# | cherry | 7 |
後述しますが、このname
属性は、データフレームの列名に関わり合う部分になっています。
pandas.DataFrame
データフレームは、テーブル形式(縦持ち)のデータ構造を持ち、列ごとに様々なデータ型(数値型、文字列型、ブール型など)を持っています。
そして、行と列の両方にインデックスを持っており、シリーズを値として持つ辞書として見ることができます。(同じインデックスを持つ複数のシリーズを結合したものをデータフレームと言います。)
データフレームを作成する最も簡単な方法は、同じ長さの1次元配列を値に持つ辞書を使う方法です。
同じ長さの1次元配列を値に持つ辞書からデータフレームを作成
data = {
'weight(g)': [295, 201, 7],
'kcal/100g': [61, 86, 60],
'brix(%)': [15, 21, 16]
}
df = pd.DataFrame(data=data)
print(df.to_markdown())
# | | weight(g) | kcal/100g | brix(%) |
# |---:|------------:|------------:|----------:|
# | 0 | 295 | 61 | 15 |
# | 1 | 201 | 86 | 21 |
# | 2 | 7 | 60 | 16 |
作成されたデータフレームは行のインデックスを指定していないので、シリーズと同じように0〜N-1までのデフォルトのインデックスが割り当てられています。
また、データフレームのvalues
属性とindex
属性、columns
属性を使うと、データ配列と行、列のインデックスをそれぞれ取得することができます。
データ配列と行、列のインデックスをそれぞれ取得
print(df.values)
# array([[295, 61, 15],
# [201, 86, 21],
# [ 7, 60, 16]])
print(df.index)
# RangeIndex(start=0, stop=3, step=1)
print(df.columns)
# Index(['weight(g)', 'kcal/100g', 'brix(%)'], dtype='object')
pandas.DataFrame
メソッドのindex
パラメータに、データ配列と同じ長さのデータラベルを設定すると、データフレームのインデックスを設定することができます。
インデックスを設定してデータフレームを作成する
df = pd.DataFrame(data=data, index=['apple', 'banana', 'cherry'])
print(df.to_markdown())
# | | weight(g) | kcal/100g | brix(%) |
# |:-------|------------:|------------:|----------:|
# | apple | 295 | 61 | 15 |
# | banana | 201 | 86 | 21 |
# | cherry | 7 | 60 | 16 |
他にも、2次元配列やシリーズからデータフレームを作成する方法もあります。
2次元配列からデータフレームを作成する
data = [
[295, 61, 15],
[201, 86, 21],
[7, 60, 16]
]
df = pd.DataFrame(data=data, index=['apple', 'banana', 'cherry'], columns=['weight(g)', 'kcal/100g', 'brix(%)'])
print(df.to_markdown())
# | | weight(g) | kcal/100g | brix(%) |
# |:-------|------------:|------------:|----------:|
# | apple | 295 | 61 | 15 |
# | banana | 201 | 86 | 21 |
# | cherry | 7 | 60 | 16 |
name属性の値が無いシリーズからデータフレームを作成する
s1 = pd.Series([295, 201, 7], index=['apple', 'banana', 'cherry'])
s2 = pd.Series([61, 86, 60], index=['apple', 'banana', 'cherry'])
s3 = pd.Series([15, 21, 16], index=['apple', 'banana', 'cherry'])
df = pd.DataFrame(data={'weight(g)': s1, 'kcal/100g': s2, 'brix(%)': s3})
print(df.to_markdown())
# | | weight(g) | kcal/100g | brix(%) |
# |:-------|------------:|------------:|----------:|
# | apple | 295 | 61 | 15 |
# | banana | 201 | 86 | 21 |
# | cherry | 7 | 60 | 16 |
name属性の値があるシリーズからデータフレームを作成する
s1 = pd.Series([295, 201, 7], index=['apple', 'banana', 'cherry'], name='weight(g)')
s2 = pd.Series([61, 86, 60], index=['apple', 'banana', 'cherry'], name='kcal/100g')
s3 = pd.Series([15, 21, 16], index=['apple', 'banana', 'cherry'], name='brix(%)')
df = pd.concat([s1, s2, s3], axis=1)
print(df.to_markdown())
# | | weight(g) | kcal/100g | brix(%) |
# |:-------|------------:|------------:|----------:|
# | apple | 295 | 61 | 15 |
# | banana | 201 | 86 | 21 |
# | cherry | 7 | 60 | 16 |
データフレームの行や列、値は以下のようにして取り出すことができます。
データフレームから列を取り出す
print(df['weight(g)'].to_markdown())
# | | weight(g) |
# |:-------|------------:|
# | apple | 295 |
# | banana | 201 |
# | cherry | 7 |
データフレームから行を取り出す
print(df.loc['banana'].to_markdown())
# | | banana |
# |:----------|---------:|
# | weight(g) | 201 |
# | kcal/100g | 86 |
# | brix(%) | 21 |
データフレームから値を取り出す
print(df.loc['banana', 'weight(g)'])
# 201
他にもデータを抽出する方法はたくさんありますが、ここでは割愛します。詳しくは、5.データ抽出を参照してください。
基本操作まとめ
シリーズ
逆引き |
コマンド |
戻り値 |
1次元配列から作成 |
pd.Series(data=[データ配列], [index=[インデックス]]) |
pd.Series |
辞書から作成 |
pd.Series(data={'インデックス': データ値,…}) |
pd.Series |
インデックスを取得 |
s.index |
pd.Index |
データ配列を取得 |
s.values |
np.ndarray |
インデックスのname属性を取得 |
s.index.name |
str |
データ配列のname属性を取得 |
s.name |
str |
一意な値のリストを取得 |
s.unique() |
np.ndarray |
一意な値の出現頻度をカウント |
s.value_counts() |
pd.Series |
辞書に変換 |
s.to_dict() |
dict |
リストに変換 |
s.to_list() |
list |
コピー |
s.copy() |
pd.Series |
マークダウンテーブルに変換 |
s.to_markdown() |
str |
関数を全要素に適用 |
s.apply(lambda x:func(x)) |
pd.Series |
データフレーム
逆引き |
コマンド |
戻り値 |
1次元配列を値に持つ辞書から作成 |
pd.DataFrame(data={'列名': arr_1d, …}) |
pd.DataFrame |
2次元配列から作成 |
pd.DataFrame(data=arr_2d, columns=[列名のリスト]) |
pd.DataFrame |
name属性がないシリーズから作成 |
pd.DataFrame(data={'列名': s1, '列名': s2, …}) |
pd.DataFrame |
name属性があるシリーズから作成 |
pd.concat([s1, s2, …], axis=1) |
pd.DataFrame |
データ配列を取得 |
df.values |
np.ndarray |
行のインデックスを取得 |
df.index |
pd.Index |
列のインデックスを取得 |
df.columns |
pd.Index |
コピー |
df.copy() |
pd.DataFrame |
転置 |
df.T |
pd.DataFrame |
マークダウンテーブルに変換 |
df.to_markdown() |
str |
関数を全要素に適用 |
df.applymap(lambda x:func(x)) |
pd.DataFrame |
データI/O
CSVファイル
このセクションで使用する追加モジュール
コマンド |
用途 |
追加のインストール |
from glob import glob |
CSVをワイルドカードを使って読み込む |
なし |
import csv |
CSVをダブルクオートして書き出す |
なし |
CSVファイルを読み込む
pandas.read_csv
メソッドを使用して、CSVファイルをpandas.DataFrame
として読み込むことができます。
pandas.read_csv
CSVファイルをデータフレームとして読み込む
df = pd.read_csv('CSVファイルのパス')
逆引き |
コマンド |
日本語が含まれるファイルを読み込む |
pd.read_csv('sample.csv', encoding='cp932') |
Pythonオブジェクト型として読み込む |
pd.read_csv('sample.csv', dtype=object) |
ヘッダーを設定して読み込む |
pd.read_csv('sample.csv', names=[列名のリスト]) |
インデックスを設定して読み込む |
pd.read_csv('sample.csv', index_col='列名') |
先頭から任意の行スキップして読み込む |
pd.read_csv('sample.csv', skiprows=行数) |
末尾から任意の行スキップして読み込む |
pd.read_csv('sample.csv', skipfooter=行数, engine='python') |
先頭から任意の行だけ読み込む |
pd.read_csv('sample.csv', nrows=行数) |
指定した列名だけ読み込む |
pd.read_csv('sample.csv', usecols=[列名のリスト]) |
ワイルドカードで読み込む |
pd.read_csv(glob('*.csv')) |
複数のCSVをまとめて1つに読み込む |
csv_files_path = sorted(glob('*.csv'))
marge_csv = [pd.read_csv(f) for f in csv_files_path]
pd.concat(marge_csv, ignore_index=True) |
複数のCSVファイルを1つのDataFrameにマージしたいときは
sample1.csv
"col1","col2"
"1001","あいうえお"
"1002","かきくけこ"
"1003","さしすせそ"
sample2.csv
"col1","col2"
"1004","たちつてと"
"1005","なにぬねの"
"1006","はひふへほ"
sample3.csv
"col1","col2"
"1007","まみむめも"
"1008","やゆよ"
"1009","らりるれろ"
for
ループと標準モジュールのglop
を使用し、指定したディレクトリからCSVファイルをまとめて順番にインポートとして、pandas.concat
メソッドで、1つのデータフレームにマージします。
csv_files_path = sorted(glob('sample*.csv'))
marge_csv = []
for f in csv_files_path:
marge_csv.append(pd.read_csv(f, encoding='cp932'))
# 1つのデータフレームに結合する
# ignore_index=Trueでインデックスをリセット
df = pd.concat(marge_csv, ignore_index=True)
print(df)
# col1 col2
# 0 1001 あいうえお
# 1 1002 かきくけこ
# 2 1003 さしすせそ
# 3 1004 たちつてと
# 4 1005 なにぬねの
# 5 1006 はひふへほ
# 6 1007 まみむめも
# 7 1008 やゆよ
# 8 1009 らりるれろ
CSVファイルを書き出す
pandas.DataFrame.to_csv
メソッドを使用して、pandas.DataFrame
をCSVファイルとして書き出すことができます。
pandas.DataFrame.to_csv
データフレームをCSVファイルとして書き出す
df.to_csv('保存先のCSVファイルのパス')
逆引き |
コマンド |
インデックスを無視して書き出す |
df.to_csv('sample.csv', index=False) |
日本語が含まれるファイルを書き出す |
df.to_csv('sample.csv', encoding='cp932') |
ダブルクオートして書き出す |
df.to_csv('sample.csv', quoting=csv.QUOTE_ALL) |
ファイルを任意の行数ごと分割して書き出す |
n=任意の行数
for index, divided_df in df.groupby(by=df.index//n): divided_df.to_csv('sample_{}.csv'.format(index)) |
【Python】PandasでCSVファイルを読み込み/書き出しする実践テクニック集
Excelファイル
このセクションで使用する追加モジュール
コマンド |
用途 |
追加のインストール |
from glob import glob |
Excelをワイルドカードを使って読み込む |
なし |
Googleスプレッドシート
このセクションで使用する追加モジュール
コマンド |
用途 |
追加のインストール |
import gspread |
スプレッドシートを操作する |
$ pip install gspread |
from oauth2client.service_account import ServiceAccountCredentials |
GoogleAPIの認証 |
$ pip install oauth2client |
PostgreSQL
このセクションで使用する追加モジュール
コマンド |
用途 |
追加のインストール |
from sqlalchemy import create_engine |
PostgreSQLに接続する |
$ pip install sqlalchemy |
PostgreSQLのテーブルを読み込む
pandas.read_sql
メソッドを使用して、PostgreSQLのテーブルをpandas.DataFrame
として読み込むことができます。
pandas.read_sql
PostgreSQLのテーブルをデータフレームとして読み込む
df = pd.read_sql(sql='SELECT * FROM テーブル名;', con=create_engine('データベースのURL'))
PostgreSQLのテーブルに追加する
pandas.DataFrame.read_sql
メソッドを使用すると、PostgreSQLに存在するテーブルにpandas.DataFrame
を追加することができます。
pandas.DataFrame.to_sql
データフレームをPostgreSQLのテーブルに追加する
df.to_sql(name='テーブル名', con=create_engine('データベースのURL'), if_exists='append', index=False)
PandasとSQLAlchemyでPostgreSQL(Heroku Postgres)を読み書きする方法
お手軽サンプルデータセットを読み込む
このセクションで使用する追加モジュール
コマンド |
用途 |
追加のインストール |
import seaborn as sns |
サンプルデータセットを読み込む |
$ pip install seaborn |
matplotlib
ラッパーのseaborn
モジュール(Pythonの可視化ライブラリ)をインポートし、seaborn.load_dataset
メソッドで、サンプルデータセットを簡単に読み込むことができます。
読み込んだデータセットはpandas.DataFrame
として格納されるので、データ処理の余計な手間が省けて便利です。
seaborn.load_dataset
seabornモジュールのデータセットを読み込む
df = sns.load_dataset('データセット名')
逆引き |
コマンド |
アヤメの品種分類データ |
sns.load_dataset('iris') |
タイタニック号の乗客データ |
sns.load_dataset('titanic') |
ダイヤモンドの価格を決めるcarat、cut、color、clarityなどに関するデータ |
sns.load_dataset('diamonds') |
2014年までに発見された1,000以上の惑星データ |
sns.load_dataset('planets') |
レストランスタッフが受け取ったチップの金額と関連データ |
sns.load_dataset('tips') |
その他のデータセットは、公式のGitHubを確認してください。
データ前処理の前処理
データの全体像を把握
データのチラ見
逆引き |
コマンド |
先頭5行を抽出 |
df.head() |
末尾5行を抽出 |
df.tail() |
行数、列数の確認
逆引き |
コマンド |
行数 |
len(df) |
列数 |
len(df.columns) |
次元数(行数と列数) |
df.shape |
データ型の処理
データ型の確認
逆引き |
コマンド |
データ型の確認 |
df.dtypes |
有効データ数、データ型、メモリ使用量の確認 |
df.info() |
キャスト(型変換)
逆引き |
コマンド |
整数型に型変換 |
df['列名'].astype('int') |
浮動小数点型に型変換 |
df['列名'].astype('float') |
文字型に型変換 |
df['列名'].astype('str') |
ブール型に型変換 |
df['列名'].astype('bool') |
Pythonオブジェクト型に型変換 |
df['列名'].astype('object') |
文字型から日時型に型変換 |
pd.to_datetime(df['列名']) |
シリアル値から日時型に型変換 |
pd.to_timedelta(df['列名'].astype('float'), unit='D') + pd.to_datetime('1900-01-01') |
複数列まとめて型変換 |
df.astype({'列名1': '型1', '列名2': '型2'}) |
全ての列を型変換 |
df.astype('型') |
欠損値の処理
欠損値の有無を確認
逆引き |
コマンド |
各列ごとの欠損値の数を確認 |
df.isnull().sum() |
欠損値の抽出
逆引き |
コマンド |
欠損値が1つでもある行を抽出 |
df[df.isnull().any(axis=1)] |
指定した1つの列名に欠損値がある行を抽出 |
df[df['列名'].isnull()] |
欠損値の削除
逆引き |
コマンド |
欠損値が1つでもある行を削除 |
df.dropna() |
指定した列に欠損値がある行を削除 |
df.dropna(subset=[列名のリスト]) |
欠損値の置換
逆引き |
コマンド |
全ての列に対して共通の値で置換 |
df.fillna('値') |
列ごとに異なる値で置換 |
df.fillna({'列名1': 値1, '列名2': 値2}) |
外れ値の確認
定性データ(質的変数)
逆引き |
コマンド |
指定した列の一意な値のリストを確認 |
df['列名'].unique() |
指定した列の一意な値の出現回数を確認 |
df['列名'].values_count() |
定量データ(量的変数)
逆引き |
コマンド |
有効データ数、平均値、標準偏差、最小値、四分位数(25%点、50%点、75%点)、最大値を確認 |
df.describe() |
時系列データ(日時型)
逆引き |
コマンド |
最初の日付を確認 |
df['列名'].min() |
最後の日付を確認 |
df['列名'].max() |
データ抽出
直接抽出
行を抽出する
逆引き |
コマンド |
戻り値 |
先頭5行を抽出 |
df.head() |
pd.DataFrame |
末尾5行を抽出 |
df.tail() |
pd.DataFrame |
1つの行名に一致する行を抽出 |
df.loc['行名'] |
pd.Series |
複数の行名に一致する行を抽出 |
df.loc[['行名1', '行名2']] |
pd.DataFrame |
行間のスライスしに一致する行を抽出 |
df.loc['行名1':'行名2'] |
pd.DataFrame |
ブール値のシリーズに一致する行を抽出 |
df.loc[ブール値のシリーズ] |
pd.DataFrame |
列を抽出する
逆引き |
コマンド |
戻り値 |
1つの列名に一致する列を抽出 |
df['列名'] |
pd.Series |
複数の列名に一致する列を抽出 |
df[['列名1', '列名2']] |
pd.DataFrame |
行と列を抽出する
逆引き |
コマンド |
戻り値 |
1つの行名と単一の列名 |
df.loc['行名', '列名'] |
str など |
1つの行名と複数の列名 |
df.loc['行名', ['列名1', '列名2']] |
pd.Series |
df.loc[['行名'], ['列名1', '列名2']] |
pd.DataFrame |
複数の行名と1つの列名 |
df.loc[['行名1', '行名2'], '列名'] |
pd.Series |
df.loc[['行名1', '行名2'], ['列名']] |
pd.DataFrame |
複数の行名と複数の列名 |
df.loc[['行名1', '行名2'], ['列名1', '列名2']] |
pd.DataFrame |
ブール値のシリーズと1つの列名 |
df.loc[ブール値のシリーズ, '列名'] |
pd.Series |
df.loc[ブール値のシリーズ, ['列名']] |
pd.DataFrame |
ブール値のシリーズと複数の列名 |
df.loc[ブール値のシリーズ, ['列名1', '列名2']] |
pd.DataFrame |
条件抽出
数値比較(比較演算子)
逆引き |
コマンド |
戻り値 |
一致 |
df.query('列名==数値') |
pd.DataFrame |
df[df['列名']==数値] |
pd.DataFrame |
未満 |
df.query('列名<数値') |
pd.DataFrame |
df[df['列名']<数値] |
pd.DataFrame |
以下 |
df.query('列名<=数値') |
pd.DataFrame |
df[df['列名']<=数値] |
pd.DataFrame |
超過 |
df.query('列名>数値') |
pd.DataFrame |
df[df['列名']>数値] |
pd.DataFrame |
以上 |
df.query('列名>=数値') |
pd.DataFrame |
df[df['列名']>=数値] |
pd.DataFrame |
以外 |
df.query('列名!=数値') |
pd.DataFrame |
df[df['列名']!=数値] |
pd.DataFrame |
文字列比較
逆引き |
コマンド |
戻り値 |
完全一致 |
df.query('列名=="文字列"') |
pd.DataFrame |
df[df['列名']=="文字列"] |
pd.DataFrame |
前方一致 |
df.query('列名.str.startswith("文字列")', engine='python') |
pd.DataFrame |
df[df['列名'].str.startswith('文字列', na=False)] |
pd.DataFrame |
後方一致 |
df.query('列名.str.endswith("文字列")', engine='python') |
pd.DataFrame |
df[df['列名'].str.endswith('文字列', na=False)] |
pd.DataFrame |
部分一致 |
df.query('列名.str.contains("文字列")', engine='python') |
pd.DataFrame |
df[df['列名'].str.contains('文字列', na=False)] |
pd.DataFrame |
正規表現一致 |
df.query('列名.str.match(r"正規表現")', engine='python') |
pd.DataFrame |
df[df['列名'].str.match(r'正規表現', na=False)] |
pd.DataFrame |
論理演算子
逆引き |
コマンド |
戻り値 |
AND(論理積) |
df.query('条件式1&条件式2') |
pd.DataFrame |
df[(ブール値のシリーズ1)&(ブール値のシリーズ2)] |
pd.DataFrame |
OR(論理和) |
df.query('条件式1|条件式2') |
pd.DataFrame |
df[(ブール値のシリーズ1)|(ブール値のシリーズ2)] |
pd.DataFrame |
NOT(補集合) |
df.query('~条件式') |
pd.DataFrame |
df[~(ブール値のシリーズ)] |
pd.DataFrame |
欠損値の抽出
逆引き |
コマンド |
戻り値 |
欠損値が1つでもある行 |
df[df.isnull().any(axis=1)] |
pd.DataFrame |
指定した1つの列名に欠損値がある行 |
df[df['列名'].isnull()] |
pd.DataFrame |
重複値の抽出
逆引き |
コマンド |
戻り値 |
すべての値が重複している行 |
df[df.duplicated()] |
pd.DataFrame |
指定した列で値が重複している行 |
df[df.duplicated(subset=[列名のリスト])] |
pd.DataFrame |
指定した列で重複していない行 |
df[~df.duplicate(subset=[列名のリスト])] |
pd.DataFrame |
ランダムサンプリング
pandas.DataFrame.sample
逆引き |
コマンド |
戻り値 |
ランダムに1行 |
df.sample() |
pd.DataFrame |
ランダムに30行 |
df.sample(n=30) |
pd.DataFrame |
ランダムに30%行 |
df.sample(frac=0.3) |
pd.DataFrame |
ランダムに30行(重複抽出を許可) |
df.sample(n=30, replace=True) |
pd.DataFrame |
ランダムに30%行(乱数値を固定) |
df.sample(frac=0.3, random_state=0) |
pd.DataFrame |
ホールドアウトセット
sklearn.model_selection.train_test_split — scikit-learn 0.23.1 documentation
構文
from sklearn.model_selection import train_test_split
Xdf = df.drop(columns='目的変数の列名') # 特徴量
ydf = df['目的変数の列名'] # 目的変数
Xtrain, Xtest, ytrain, ytest = train_test_split(
Xdf, # 第1引数、特徴量の2次元配列 : arr_2d, np.ndarray, pd.DataFrame, sp.sparse
ydf, # 第2引数、目的変数の1次元配列 : arr_2d, np.ndarray, pd.DataFrame, sp.sparse
test_size=0.3, # テスト用データのサイズ。Noneの場合、train_sizeの補数 : float, default=0.25
train_size=None, # 学習用データのサイズ。Noneの場合、test_sizeの補数 : float, default=None
random_state=1, # 乱数値を固定 : int, default=None
)
# Returns:
# Xtrain : 学習用データの特徴量マトリックス。DataFrame
# Xtest : テスト用データの特徴量マトリックス。Series
# ytrain : 学習用データの目的変数の配列。DataFrame
# ytest : テストデータの目的変数の配列。Series
データ操作
インデックス
行のインデックス
逆引き |
コマンド |
行のインデックスを取得 |
df.index |
行のインデックスを上書きする |
df.index = ['同じ要素数のリスト'] |
列を行のインデックスにセット |
df.index = df.set_index('列名') |
行のインデックスを振り直す |
df.index = df.reset_index(drop=True) |
行名を変更する |
df.rename(index={'行名1':'新しい行名1', '行名2':'新しい行名2'}) |
列のインデックス(ヘッダー)
逆引き |
コマンド |
列のインデックスを取得 |
df.columns |
列のインデックスを上書きする |
df.columns = ['同じ要素数のリスト'] |
列名を変更する |
df.rename(columns={'列名1':'新しい列名1', '列名2':'新しい列名2'}) |
キャスト(型変換)
逆引き |
コマンド |
整数型に型変換 |
s.astype('int') |
浮動小数点型に型変換 |
s.astype('float') |
文字型に型変換 |
s.astype('str') |
ブール型に型変換 |
s.astype('bool') |
Pythonオブジェクト型に型変換 |
s.astype('object') |
文字型から日時型に型変換 |
pd.to_datetime(s) |
シリアル値から日時型に型変換 |
pd.to_timedelta(s.astype('float'), unit='D') + pd.to_datetime('1900-01-01') |
複数列まとめて型変換 |
df.astype({'列名1': '型1', '列名2': '型2'}) |
全ての列を型変換 |
df.astype('型') |
並び替え
インデックスを基準
逆引き |
コマンド |
行名で昇順ソート |
df.sort_index() |
行名で降順ソート |
df.sort_index(ascending=False) |
辞書で行名を昇順ソート |
df['order'] = df.index.map({'行名1': 1, '行名2': 2, …})
df.sort_values(by=['order']).drop(columns=['order']) |
列名で昇順ソート |
df.sort_index(axis=1) |
辞書で列名を昇順ソート |
df.loc['order'] = df.columns.map({'列名1': 1, '列名2': 2, …})
df.sort_values(by=['order'], axis=1).drop(index=['order']) |
データを基準
逆引き |
コマンド |
指定した列の値で昇順ソートする |
df.sort_values(by='列名') |
指定した列の値で降順ソートする |
df.sort_values(by='列名', ascending=False) |
指定した複数の列の値でソートする |
df.sort_values(by=[列名のリスト]) |
指定した列の値を辞書でソートする |
df['order'] = df['列名'].map({'値1': 1, '値2': 2, …})
df.sort_values(by='order').drop(columns=['order']) |
削除
逆引き |
コマンド |
行名を指定して行を削除 |
df.drop(index=[行名のリスト]) |
列名を指定して列を削除 |
df.drop(columns=[列名のリスト]) |
欠損値が1つでもある行を削除 |
df.dropna() |
指定した列に欠損値がある行を削除 |
df.dropna(subset=[列名のリスト]) |
指定した列で重複している行を削除 |
df[~df.duplicate(subset=[列名のリスト])] |
置換
逆引き |
コマンド |
完全一致の辞書で置換 |
s.apply(lambda x: {'検索値': '置換値', …}.get(x, x)) |
正規表現に一致した箇所を置換 |
s.astype('str').str.replace(r'正規表現', '置換値') |
ブール値のシリーズに一致したら値を代入 |
df.loc[ブール値のシリーズ, '列名'] = '値' |
結合
ユニオン(縦方向)
逆引き |
コマンド |
データフレーム同士を縦方向に結合 |
pd.concat([df1, df2], ignore_index=True) |
ジョイン(横方向)
逆引き |
コマンド |
列名を基準にデータフレーム同士を横方向に結合 |
pd.merge(left=df1, right=df2, on=[列名のリスト], how='left') |
行名を基準にデータフレーム同士を横方向に結合 |
pd.merge(left=df1, right=df2, left_index=True, right_index=True) |
行名(右)と列名(左)を基準にデータフレーム同士を横方向に結合 |
pd.merge(left=df1, right=df2, left_on='列名', right_index=True) |
行名(左)と列名(右)を基準にデータフレーム同士を横方向に結合 |
pd.merge(left=df1, right=df2, left_index=True, right_on='列名') |
集計(要約統計量)
逆引き |
コマンド |
戻り値 |
データフレームの要約統計量 |
df.describe() |
pd.DataFrame |
シリーズの有効データ数 |
s.count() |
int |
シリーズの一意な値の数 |
s.nunique() |
int |
シリーズの有効データの合計値 |
s.astype('float').sum() |
float |
シリーズの有効データの平均値 |
s.astype('float').mean() |
float |
シリーズの有効データの中央値 |
s.astype('float').median() |
float |
シリーズの有効データの最頻値 |
s.astype('float').mode() |
pd.Series |
シリーズの有効データの最小値 |
s.astype('float').min() |
float |
シリーズの有効データの最大値 |
s.astype('float').max() |
float |
シリーズの有効データの不偏歪度 |
s.astype('float').skew() |
float |
シリーズの有効データの不偏尖度 |
s.astype('float').kurt() |
float |
シリーズの有効データの不偏標準偏差 |
s.astype('float').std() |
float |
シリーズの有効データの不偏標準誤差 |
s.astype('float').sem() |
float |
集約(groupby、pivot_table)
1つの定性データの列をグルーピング
1つの定性データの列をグルーピングし、その他の定量データの列にさまざまな集約関数を適用する場合は、pandas.DataFrame.groupby
メソッドでグルーピングし、pandas.DataFrame.agg
メソッドでまとめて集約関数を適用させます。
pandas.DataFrame.groupby
pandas.DataFrame.agg
構文と使用例
df.groupby(
by='sex', # グルーピングする列名 : column, list of columns
# axis=1, # グルーピングする方向 : {0 or 'index', 1 or 'columns'}, default 0
# as_index=False, # グループラベルをインデックスにする : bool, default True
).agg(
{'age': ['min', 'median', 'max']} # 列名と集約関数の1次元配列でマッピングされた辞書
)
# Returns:
# DataFrame
aggメソッドで使える集約関数
逆引き |
集約関数 |
データ数 |
'size' |
有効データ数 |
'count' |
有効データのユニーク値の数 |
'nunique' |
合計値 |
'sum' |
最小値 |
'min' |
最大値 |
'max' |
平均値 |
'mean' |
中央値 |
'median' |
最頻値 |
pd.Series.mode |
不偏歪度 |
'skew' |
不偏尖度 |
pd.Series.kurt |
不偏標準偏差 |
'std' |
不偏標準誤差 |
'sem' |
2つの定性データの列をグルーピング(ダイナミッククロス集計)
2つの定性データの列をグルーピングし、その他の定量データの列にさまざまな集約関数を適用しダイナミッククロス集計を行う場合は、pandas.DataFrame.pivot_table
メソッドを使用します。
pandas.DataFrame.pivot_table
構文と使用例
df.pivot_table(
index=['sex', 'class'], # グルーピングする列名(行) : column, list of columns
columns='survived', # グルーピングする列名(列) : column, list of columns
values='fare', # 集約関数を適用する列名 : column, list of columns
aggfunc=['count', np.mean], # 集約関数 : function, list of functions, default np.mean
# fill_value=0, # 集計後の欠損値を指定した値で穴埋め : scalar, default None
# margins=True, # カテゴリごとの小計・総計を算出 : bool, default False
# margins_name='All', # 小計・総計のラベル名を変更 : str, default 'All'
)
# Returns:
# Excel形式のピボットテーブル。DataFrame
aggfuncパラメータで使える集約関数
逆引き |
集約関数 |
データ数 |
np.size |
有効データ数 |
'count' , pd.Series.count |
有効データのユニーク値の数 |
pd.Series.nunique |
合計値 |
'sum' , np.sum |
最小値 |
'min' , np.min |
最大値 |
'max' , np.max |
平均値 |
'mean' , np.mean |
中央値 |
'median' , np.median |
最頻値 |
pd.Series.mode |
不偏歪度 |
'skew' , pd.Series.skew |
不偏尖度 |
pd.Series.kurt |
不偏標準偏差 |
'std' , pd.Series.std |
不偏標準誤差 |
'sem' , pd.Series.sem |
文字列メソッド
時系列メソッド
ビニング
ビニング処理とは、連続する定量データを任意の境界値でセグメントし、定性データへとカテゴリ分けして離散値に変換する処理のことをいいます
MEMO
例えば11歳、24歳をそれぞれ10代、20代のように、年齢を
年齢幅に変更するなどです。
pandasでビニング処理を行う場合、pandas.cut
メソッドを使います
pandas.cut — pandas 1.0.3 documentation
構文と使用例
df['generation'] = pd.cut(
x=df['age'],
bins=[-1, 17, 24, 34, 44, 54, 64, df['age'].max()], # 要素数で等分割または境界値を指定して分割 : int, sequence of scalars
labels=['0-17', '18-24', '25-34', '35-44', '45-54', '55-64', '65-'] # 返されるビンのラベルを指定 : array or False, default None
# right= False, # 左右どちらのエッジを含めるか指定 : bool, default True
# retbins=True, # 境界値のリストを返すかどうか : bool, default False
)
# Returns:
# out : ビニング処理されたシリーズ。Categorical, Series, or ndarray
# bins : 境界値のリスト(retbins=Trueの場合のみ)。numpy.ndarray or IntervalIndex
スケール変換(正規化/標準化)
機械学習で桁数の異なるデータをまとめて扱うときは、スケール変換を行います。
しかし、pandasには定量データを直接『正規化』または『標準化』する関数は用意されていません。そこで、scikit-learn
モジュールを使用した方法を紹介します。
正規化
定量データの特徴量を0
から1
の範囲にスケール変換する正規化は、sklearn.preprocessing.MinMaxScaler
メソッドで行います。
sklearn.preprocessing.MinMaxScaler — scikit-learn 0.23.1 documentation
使用例
from sklearn import preprocessing as pp
# 正規化する
scaler = pp.MinMaxScaler()
df[['age', 'fare']] = scaler.fit_transform(df[['age', 'fare']])
# 要約統計量を表示
print(df[['age', 'fare']].describe().to_markdown())
# | | age | fare |
# |:------|-----------:|------------:|
# | count | 714 | 891 |
# | mean | 0.367921 | 0.0628584 |
# | std | 0.18254 | 0.0969951 |
# | min | 0 | 0 | <--
# | 25% | 0.247612 | 0.0154401 |
# | 50% | 0.346569 | 0.0282127 |
# | 75% | 0.472229 | 0.060508 |
# | max | 1 | 1 | <--
標準化
定量データの特徴量を平均0
、標準偏差1
にスケール変換する標準化は、sklearn.preprocessing.StandardScaler
メソッドで行います。
sklearn.preprocessing.StandardScaler — scikit-learn 0.23.1 documentation
使用例
from sklearn import preprocessing as pp
# 標準化する
scaler = pp.StandardScaler()
df[['age', 'fare']] = scaler.fit_transform(df[['age', 'fare']])
# 要約統計量を表示
print(df[['age', 'fare']].describe().to_markdown())
# | | age | fare |
# |:------|--------------:|--------------:|
# | count | 714 | 891 |
# | mean | 2.17419e-16 | -4.37361e-17 | <--
# | std | 1.0007 | 1.00056 | <--
# | min | -2.01698 | -0.648422 |
# | 25% | -0.659542 | -0.489148 |
# | 50% | -0.117049 | -0.357391 |
# | 75% | 0.571831 | -0.0242464 |
# | max | 3.46513 | 9.66717 |
ダミー変数化
マルチインデックス