Pythonをときどき使う自分は、コードの細かい書き方をすぐに忘れてしまい、毎回同じサイトや本を見たりすることになります。内容は何度も見て知っているので、書き方だけをちょっと思い出したい、という場面がしょっちゅうあります。そんなときに、よく使うコードの文例が1ページにまとまっているサイトがあると便利かなと思います。
そんな目的で、今回はPandasについて、自分が良く使うコードの部品を以下に書いていきます。
解説については、冒頭に挙げた参考ページを見ていただければと思います。また、各項目にもリンクを貼ってあります。項目ごとのリンク集としても使えるかなと思います。
随時更新していきます。
動作確認:Python 3.7.9、Pandas 1.1.2
よく参考にするページ
- note.nkmk.me | Pandas 関連記事まとめ
- pyてよn日記 | Python:Pandas チートシート
- データ分析で頻出のPandas基本操作
- データサイエンティスト協会 | データサイエンス100本ノック(構造化データ加工編)
- 10 minutes to pandas
基本操作
import numpy as np # numpyのimport
import pandas as pd # pandasのimport
pd.__version__ # バージョン確認
データフレームの作成(1)
- データフレームを新規作成する。
# パターン1
cols = ['A', 'B', 'C', 'D'] # columns=list('ABCD')でもよい
a = np.random.randn(5,4)
df = pd.DataFrame(a, columns=cols)
# パターン2 : 空のデータフレームを作って、後からデータ(行)を追加(よく使う)
cols = ['A', 'B', 'C', 'D']
df = pd.DataFrame(index=[], columns=cols)
dfa = pd.DataFrame(np.random.randn(5,4), columns=cols)
df = df.append(dfa).reset_index(drop=True)
# パターン3 : リストからデータフレームを作成
# 1行4列
cols = ['A', 'B', 'C', 'D']
list = [[1, 2, 3, 4]]
df = pd.DataFrame(list, columns=cols)
# 4行1列
cols = ['A']
list = [1, 2, 3, 4]
df = pd.DataFrame(list, columns=cols)
# データフレームのリストの作成
df = pd.DataFrame(np.random.randn(10, 4))
pieces = [df[:3], df[3:7], df[7:]]
データフレームの作成(2) Numpyの配列から
- Numpyの配列からデータフレームを新規作成する。
cols = ['x', 'y', 'z']
a = np.random.randn(10,2)
b = np.linspace(0, 1, 10)[:,np.newaxis] # newaxisを用いて行ベクトルの作成
c = np.hstack([a,b]) # 配列の水平方向への結合
df = pd.DataFrame(c, columns=cols)
CSVファイルの読み込み、書き出し
- csvファイルの読み込み
- pandasでcsv/tsvファイル読み込み(read_csv, read_table)
filename = 'data.csv'
df = pd.read_csv(filename) # 何も指定しないと1行目がheaderとして認識され、列名columnsに割り当てられる。
df = pd.read_csv(filename, header=None) # header=Noneとすると連番[0,1,…]が列名columnsに割り当てられる。
df = pd.read_csv(filename, names=list('ABCD')) # 任意の値[names]を列名として設定
df = pd.read_csv(filename, header=2) # headerで指定した行からデータが読み込まれ、それより上の行は無視される。
df = pd.read_csv(filename, index_col=0) # index_col=0のようにindexとして使いたい列の列番号を0始まりで指定する。
# 環境によってはWarningが出るので、下記のように引数engine='python'を指定する。
df = pd.read_csv(filename, skiprows=2, skipfooter=1, engine='python') # スキップする行数を指定(初めと終わり)
df = pd.read_csv(filename, nrows=1) # 行数を指定
df = pd.read_csv(filename, sep=',') # 区切り文字を指定(コンマ)、その他 スペースやタブ区切りの場合は、sep=' ', sep='\t'
df.to_csv('data.csv')
df.to_csv('data.csv', header=False, index=False) #ヘッダー、カラムなし
df.to_csv('data.csv', header=False, index=False, encoding='utf-8') # python3は'utf-8がデフォルト
df.to_csv('data.csv', header=False, index=False, encoding='shift_jis') # 日本語を含むファイルをエクセルなどで使う場合
df.to_csv('data.csv', float_format='%10.3f') #フォーマットを指定
df.to_csv('data.tsv', sep='\t') # タブ区切り
- 固定書式ファイルの読み込み
固定書式ファイルは、例えば、”8F10.3″のように表現されるルールに従って記述されているデータ形式
(”8F10.3″は「1行につき浮動小数点(FLOAT)型が小数点以下3桁で10桁分の幅が8個連続している」という意味) - pandasでcsvを複数の区切り文字で区切って読み込むの巻
- 【プログラムTIPS】PYTHONでCSVファイルを固定書式に変換する
filename = 'data.txt' #8F10.3のデータ形式の場合
colspecs = [(0,10),(11,20),(21,30),(31,40),(41,50),(51,60),(61,70),(71,80)]
df = pd.read_fwf(filename, skiprows=1, header=None, colspecs=colspecs)
その他データの読み込み、書き出し
- クリップボードのデータの読み込み、書き出しは、エクセルからのデータをデータフレームにしたり、データフレームのデータをエクセルに貼りつけたりするときに便利!
df = pd.read_clipboard() #クリップボードからのデータの読み込み
df = pd.read_clipboard(sep=',') # 区切り文字を指定する場合
df.to_clipboard() #クリップボードへのデータの書き込み
df.to_clipboard(sep=',') #区切り文字を指定する場合
データの表示・確認
- データの内容を表示、確認する。
## データの表示、確認
df.describe # データのサマリー
df.head() # データの初めの部分
df.tail() # データの終わりの部分
df.index # インデックス
df.columns # カラム
データ型の指定、変換
- pandasのデータ型dtype一覧とastypeによる変換(キャスト)
- 時系列データについては後述
## データの型を表示
s.dtype #Seriesの場合
df.dtypes #Dataflameの場合
## データの型を指定
s = pd.Series([0, 1, 2], dtype='float64') # 倍精度浮動小数点型
s = pd.Series([0, 1, 2], dtype='int64') # 符号あり64ビット整数型
## データの型を変換
# Seriesの場合
s_f = s.astype('float64')
# Dataflemeの場合
cols = ['A', 'B', 'C', 'D']
a = [[11, 12, 13, 14],[21, 22, 23, 24]]
df = pd.DataFrame(a, columns=cols, dtype='int64')
df_f = df.astype('float64') #一括変換
df_f = df.astype({'A':'float64'}) #任意の1列
df_f = df.astype({'A':'float64'}, {'C':'str'}) #任意の複数列
データの選択
## データの選択
df['A'] #カラム名による列の選択
df.A # 同上
df[['A','C']] #複数カラムの場合
df[0:3] #インデックス番号による行の選択
# .locによる行と列の選択(ラベルを使用)
df.loc[:,['A','B']] # 複数列の選択
df.loc[0:2,['A','B']] # 複数列、複数行の選択
# .ilocによる行と列の選択(インデックス番号、カラム番号を使用)
df.iloc[2] # インデックスNoを指定して行を選択
df.iloc[1:3,:2] # インデックスNo、カラムNoを指定して行、列を選択
df[df['A'] > 0] # 特定の条件を指定しての行、列の選択
データの結合
- Pandas_Cheat_Sheet
- 10 minutes to pandas :Merge
- pandas.DataFrame, Seriesを連結するconcat
- pandas.DataFrameに列や行を追加(assign, appendなど)
# サンプルの作成
df1 = pd.DataFrame({'A': ['A1', 'A2', 'A3'],
'B': ['B1', 'B2', 'B3'],
'C': ['C1', 'C2', 'C3']},
index=['ONE', 'TWO', 'THREE'])
df2 = pd.DataFrame({'C': ['C2', 'C3', 'C4'],
'D': ['D2', 'D3', 'D4']},
index=['TWO', 'THREE', 'FOUR'])
# Concatを使う場合
pd.concat([df1, df2]) # 結合するデータフレームをリストやタプルで指定
pd.concat([df1, df2, df1]) # 3つ以上でもOK
pd.concat([df1, df2], axis=0) # 縦方向に連結(デフォルト)
pd.concat([df1, df2], axis=1) # 横方向に連結
pd.concat([df1, df2], join='outer') #外部結合(全ての列(または行)が残る)
pd.concat([df1, df2], join='inner') #外部結合(共通の列(または行)のみが残る)
# appendを使う場合
df1.append(df2) #df1にdf2を縦方向に連結
df1.append([df1, df2]) #リストやタプルで複数も可
データの抽出(queryを中心に)
# サンプルの作成
df1 = pd.DataFrame({'A': range(1, 6),
'BB': range(10, 0, -2),
'C C': range(10, 5, -1)})
df2 = pd.DataFrame({'A': ['A1', 'D2', 'H3'],
'B': ['AB1', 'BC2', 'CD3'],
'C': ['ABC1', 'BBC2', 'CBC3']},
index=['ONE', 'TWO', 'THREE'])
# シンプルな書き方
df1[df1.A > df1.BB]
df1[df1.BB == df1['C C']]
# queryを使う場合
df1.query('A > BB')
df1.query('BB == `C C`') #文字列にスペースを含む場合は、バッククォートで囲う
df1.query('BB != `C C`')
df1.query('A > BB & A > 9') # A>BB かつ A>9
df1.query('A > BB | A >= 5') # A>BB または A>=5
a = 5
df1.query('A > BB | A >= {}'.format(a)) # A>BB または A>=5(変数を使う場合)
df2.query('B.str.startswith("A")', engine='python') #B列が文字列Aで始まる行
df2.query('B.str.endswith("2")', engine='python') #B列が文字列2で終わる行
df2.query('C.str.contains("CBC")', engine='python') #C列が文字列CBCを含む行
df2.query('A.str.contains("^[D-J]", regex=True)', engine='python') #A列がアルファベットのD~Jのいずれかを含む行
df2.query('A.str.contains("^[B-H].*[2-9]$", regex=True)', engine='python') #A列の先頭がアルファベットのB~Hではじまり、末尾が数字の3~9で終わる行
時系列データ
- Pandasドキュメント Time series / date functionality
- pandasで日付・時間の列を処理(文字列変換、年月日抽出など)
- 日付のフォーマット:8.1. datetime — 基本的な日付型および時間型 — Python 3.6.5 ドキュメント
# 基本
import datetime # 日付と時刻を扱うためのpythonの基本オブジェクト
start = datetime.datetime(2011, 1, 1)
end = datetime.datetime(2012, 1, 1)
index = pd.date_range(start, end)
index = pd.date_range(start, end, freq='D') # D:日次
index = pd.date_range(start, end, freq='H') # H:毎時、T:毎分、S:毎秒
index = pd.date_range(start, periods=1000, freq="M") # M:月末ごと、MS:毎月初
index = pd.date_range(start, periods=1000, freq="W") # W:週次
index = pd.period_range("2018-04", "2020-12", freq='M') # 月ごと
index.days_in_month #月の日数を取得
- 時間によるインデックスと抽出
dft1 = pd.DataFrame(
np.random.randn(100000, 1),
columns=["A"],
index=pd.date_range("20130101", periods=100000, freq="T"),)
dft1.loc["2013"] # 2013年を抽出
dft1.loc["2013-1":"2013-2"] # 期間を指定して抽出(その1)
dft1.loc["2013-1-15":"2013-1-15 12:30:00"] # 期間を指定して抽出(その2)
- 型変換とフォーマット
- pandas 文字列⇒Datetime変換|時系列操作を簡単マスター!
dft2 = pd.DataFrame({'A': ['2017-11-01 12:24', '2017-11-18 23:00', '2017-11-18 23:00'],
'B': ['2017年11月1日 12時24分', '2017年11月18日 23時00分', '2017年12月5日 5時05分']})
print(dft2.dtypes, type(dft2['A'][0])) #いずれの列もobject型(各要素は文字列str型)
dft2['A'] = pd.to_datetime(dft2['A']) # datetime64[ns]型への変換
dft2['B'] = pd.to_datetime(dft2['B'], format='%Y年%m月%d日 %H時%M分') # フォーマットの指定
欠損値の扱い
# 欠損値を削除
df.dropna(how='all') # すべての値が欠損値NaNである行を削除
df.dropna((how='all', axis=1)) # 列の場合
df2.dropna(how='any') # 欠損値が一つでも含まれる行を削除
# 欠損値を置換、穴埋め
df.fillna(0) # 欠損値NaNを共通の値で一律に置換(この場合は0で置換) もとのオブジェクトは変更されないことに注意!
df.fillna(0, inplace=True) # もとのオブジェクトを変更
df.fillna(method='ffill') # 前(上)の値で置換
df.fillna(method='bfill') # 後ろ(下)の値で置換
以下、更新中