pandasの基本操作#
はじめに#
本稿ではpandas(Python Data Analysis Library)と呼ばれる、Pythonでのデータ分析を効率的に行うためのライブラリに関して、その基本的な操作方法を紹介します。pandasではデータの読み込み・統計量の算出・整形・可視化・書き出しなど、データ分析で頻出の作業を簡単に行うことができます。また、オープンソース(BSDライセンス)で公開されているため、個人/商用問わず無料で利用できます。
pandasの公式チュートリアルをベースに、基本操作を紹介していきます。 本稿で紹介するpandasの基本操作は以下の通りです。
オブジェクトの作成
データの確認
データの取得
欠損データの処理
データの操作
データの結合
グルーピング
時系列データの処理
データの可視化
データの書き出し・読み込み
オブジェクトの作成#
本章では、データを格納するオブジェクトの作成方法を紹介します。データをpandasのオブジェクトに格納することで、pandasが提供する、分析を効率化するためのさまざまな機能を利用できるようになります。
データを格納するオブジェクトには、主にSeriesとDataFrameの2種類存在します。簡単に言えば、Seriesは一次元配列、DataFrameは二次元配列です。ただし、連番以外の「インデックス」を持つことができるなど、同様のデータオブジェクト(組み込み型のlistやNumPyの二次元配列)よりも高い機能を有しています。
それでは、早速オブジェクトを作成してみましょう。
Seriesオブジェクトの作成
DataFrameオブジェクトの作成
import numpy as np
import pandas as pd # 慣例としてpdという略称で定義する
Seriesオブジェクトの作成#
pandasの Series()
関数によって、Seriesオブジェクトを作成できます。さまざまな引数がありますが、ここでは主要なもののみを紹介します。(詳細は公式ページ)
pandas.Series(data=None, index=None, name=None)
data
: Seriesオブジェクトに渡すデータを指定(list
やNumPyの一次元配列など)index
: Seriesオブジェクトに渡すインデックスを指定(list
やNumPyの一次元配列など)name
: Seriesオブジェクトの名前を指定(str
)
# Seriesオブジェクトの作成
s = pd.Series([1, 3, 5, np.nan, 6, 8])
display(s)
0 1.0
1 3.0
2 5.0
3 NaN
4 6.0
5 8.0
dtype: float64
DataFrameオブジェクトの作成#
pandasの DataFrame()
関数によって、DataFrameオブジェクトを作成できます。さまざまな引数がありますが、ここでは主要なもののみを紹介します。(詳細は公式ページ)
pandas.DataFrame(data=None, index=None, columns=None)
data
: DataFrameオブジェクトに渡すデータを指定(NumPyの二次元配列など)index
: DataFrameオブジェクトに渡すインデックスを指定(list
やNumPyの一次元配列など)columns
: DataFrameオブジェクトに渡すカラム名を指定(list
やNumPyの一次元配列など)
# DataFrameのインデックスをDatetime型で作成
dates = pd.date_range("20130101", periods=6)
display(dates)
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
'2013-01-05', '2013-01-06'],
dtype='datetime64[ns]', freq='D')
# DataFrameオブジェクトの作成
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list("ABCD"))
display(df)
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.166328 | -2.136717 | -1.079066 | 0.412360 |
2013-01-02 | -0.346681 | -0.426526 | 0.518986 | -0.608594 |
2013-01-03 | 0.305456 | -0.382561 | 0.723871 | -0.209471 |
2013-01-04 | -0.788086 | 0.588946 | 1.426202 | 0.289746 |
2013-01-05 | -0.503083 | 0.567122 | 1.287743 | -0.014255 |
2013-01-06 | 0.299511 | -1.941320 | 1.391943 | 1.173333 |
# DataFrameオブジェクトはdict型データからも作成可能
# また、カラムごとに異なるデータ型を持たせることも可能
df2 = pd.DataFrame(
{
"A": 1.0,
"B": pd.Timestamp("20130102"),
"C": pd.Series(1, index=list(range(4)), dtype="float32"),
"D": np.array([3] * 4, dtype="int32"),
"E": pd.Categorical(["test", "train", "test", "train"]),
"F": "foo",
}
)
display(df2)
display(df2.dtypes)
A | B | C | D | E | F | |
---|---|---|---|---|---|---|
0 | 1.0 | 2013-01-02 | 1.0 | 3 | test | foo |
1 | 1.0 | 2013-01-02 | 1.0 | 3 | train | foo |
2 | 1.0 | 2013-01-02 | 1.0 | 3 | test | foo |
3 | 1.0 | 2013-01-02 | 1.0 | 3 | train | foo |
A float64
B datetime64[ns]
C float32
D int32
E category
F object
dtype: object
データ確認#
本章では、オブジェクトに格納したデータを確認するさまざまな方法を紹介します。紹介する内容は以下の通りです。
先頭数行・終端数行の確認
インデックス・カラムの確認
NumPyの二次元配列形式に変換して確認
データの統計量の確認
データを転置して確認
特定の軸・要素に対して降順・昇順に並べ替えて確認
先頭数行・終端数行の確認#
Series、DataFrameの head()
メソッドによって先頭\(n\)行を、 tail()
メソッドによって終端\(n\)行を確認できます。
DataFrame.head(n=5)
(詳細は公式ページ)
n
: 先頭から取り出す行数を指定(デフォルトは5)
DataFrame.tail(n=5)
(詳細は公式ページ)
n
: 終端から取り出す行数を指定(デフォルトは5)
# 先頭数行の確認
display(df.head()) # デフォルトは先頭5行分
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.166328 | -2.136717 | -1.079066 | 0.412360 |
2013-01-02 | -0.346681 | -0.426526 | 0.518986 | -0.608594 |
2013-01-03 | 0.305456 | -0.382561 | 0.723871 | -0.209471 |
2013-01-04 | -0.788086 | 0.588946 | 1.426202 | 0.289746 |
2013-01-05 | -0.503083 | 0.567122 | 1.287743 | -0.014255 |
# 終端数行の確認
display(df.tail(3)) # 引数に整数を指定すると、その分の行を確認できる
A | B | C | D | |
---|---|---|---|---|
2013-01-04 | -0.788086 | 0.588946 | 1.426202 | 0.289746 |
2013-01-05 | -0.503083 | 0.567122 | 1.287743 | -0.014255 |
2013-01-06 | 0.299511 | -1.941320 | 1.391943 | 1.173333 |
インデックス・カラムの確認#
Series、DataFrameの index
プロパティによってインデックスを、DataFrameの columns
プロパティによってカラムを確認できます。
DataFrame.index
(詳細は公式ページ)
DataFrame.columns
(詳細は公式ページ)
# インデックスの確認
display(df.index)
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
'2013-01-05', '2013-01-06'],
dtype='datetime64[ns]', freq='D')
# カラムの確認
display(df.columns)
Index(['A', 'B', 'C', 'D'], dtype='object')
NumPyの二次元配列形式に変換して確認#
DataFrameの to_numpy()
メソッドによってNumPyの二次元配列形式に変換して確認できます。なお、変換された二次元配列にはインデックスとカラムは含まれません。
DataFrame.to_numpy()
(詳細は公式ページ)
# NumPyの二次元配列に変換して確認
# なお、変換された二次元配列にはインデックスとカラムは含まれない
display(df.to_numpy())
display(df2.to_numpy())
array([[ 0.16632788, -2.13671679, -1.07906646, 0.41235954],
[-0.34668051, -0.42652624, 0.51898578, -0.6085936 ],
[ 0.30545645, -0.38256099, 0.72387141, -0.20947113],
[-0.78808582, 0.58894566, 1.42620156, 0.28974615],
[-0.50308337, 0.56712154, 1.28774348, -0.01425486],
[ 0.29951098, -1.94132013, 1.3919435 , 1.17333286]])
array([[1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'test', 'foo'],
[1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'train', 'foo'],
[1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'test', 'foo'],
[1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'train', 'foo']],
dtype=object)
データの統計量の確認#
DataFrameの describe()
メソッドによってデータの統計量を確認できます。具体的には、数値データカラムに対して、個数・平均・標準偏差・各種パーセンタイル値を確認できます。
DataFrame.describe()
(詳細は公式ページ)
# データの統計量の確認
# 数値データカラムに対して、個数・平均・標準偏差・各種パーセンタイル値を確認できる
display(df.describe())
A | B | C | D | |
---|---|---|---|---|
count | 6.000000 | 6.000000 | 6.000000 | 6.000000 |
mean | -0.144426 | -0.621843 | 0.711613 | 0.173853 |
std | 0.464733 | 1.184138 | 0.953855 | 0.610544 |
min | -0.788086 | -2.136717 | -1.079066 | -0.608594 |
25% | -0.463983 | -1.562622 | 0.570207 | -0.160667 |
50% | -0.090176 | -0.404544 | 1.005807 | 0.137746 |
75% | 0.266215 | 0.329701 | 1.365893 | 0.381706 |
max | 0.305456 | 0.588946 | 1.426202 | 1.173333 |
データを転置して確認#
DataFrameの T
プロパティによってデータを転置して確認できます。
DataFrame.T
(詳細は公式ページ)
# データを転置して確認
display(df.T)
2013-01-01 | 2013-01-02 | 2013-01-03 | 2013-01-04 | 2013-01-05 | 2013-01-06 | |
---|---|---|---|---|---|---|
A | 0.166328 | -0.346681 | 0.305456 | -0.788086 | -0.503083 | 0.299511 |
B | -2.136717 | -0.426526 | -0.382561 | 0.588946 | 0.567122 | -1.941320 |
C | -1.079066 | 0.518986 | 0.723871 | 1.426202 | 1.287743 | 1.391943 |
D | 0.412360 | -0.608594 | -0.209471 | 0.289746 | -0.014255 | 1.173333 |
特定の軸・要素に対して降順・昇順に並べ替えて確認#
Series、DataFrameの sort_index()
メソッドによって特定の軸に沿って並べ替えて、 sort_values()
メソッドによって要素の値に応じて並べ替えて確認することができます。それぞれさまざまな引数がありますが、ここでは主要なもののみを紹介します。
DataFrame.sort_index(axis=0, ascending=True)
(詳細は公式ページ)
axis
: 要素を並べ替える軸を選択(デフォルトはインデックス方向)ascending
: 昇順・降順を選択(デフォルトは昇順、True
orFalse
)
DataFrame.sort_values(by, axis=0, ascending=True)
(詳細は公式ページ)
by
: 要素を並べ替える基準カラムを選択(str
やlist
など)axis
: 要素を並べ替える軸を選択(デフォルトはインデックス方向)ascending
: 昇順・降順を選択(デフォルトは昇順、True
orFalse
)
# 特定の軸に対して降順に並べ替えて確認
# デフォルトはインデックス方向・昇順だが、ここではカラム方向・降順で並べ替える
display(df.sort_index(axis=1, ascending=False))
D | C | B | A | |
---|---|---|---|---|
2013-01-01 | 0.412360 | -1.079066 | -2.136717 | 0.166328 |
2013-01-02 | -0.608594 | 0.518986 | -0.426526 | -0.346681 |
2013-01-03 | -0.209471 | 0.723871 | -0.382561 | 0.305456 |
2013-01-04 | 0.289746 | 1.426202 | 0.588946 | -0.788086 |
2013-01-05 | -0.014255 | 1.287743 | 0.567122 | -0.503083 |
2013-01-06 | 1.173333 | 1.391943 | -1.941320 | 0.299511 |
# 特定の要素に対して昇順に並べ替えて確認
display(df.sort_values(by="B"))
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.166328 | -2.136717 | -1.079066 | 0.412360 |
2013-01-06 | 0.299511 | -1.941320 | 1.391943 | 1.173333 |
2013-01-02 | -0.346681 | -0.426526 | 0.518986 | -0.608594 |
2013-01-03 | 0.305456 | -0.382561 | 0.723871 | -0.209471 |
2013-01-05 | -0.503083 | 0.567122 | 1.287743 | -0.014255 |
2013-01-04 | -0.788086 | 0.588946 | 1.426202 | 0.289746 |
データの取得#
本章では、オブジェクトに格納したデータを取得する方法を紹介します。紹介する内容は以下の通りです。なお、要素の追加・置換に関しても紹介します。
カラム選択やスライスによるデータ取得
ラベル指定で取得
位置指定で取得
Booleanで取得
要素の追加・置換
カラム選択やスライスによる取得#
# カラム選択によるデータ取得
display(df["A"]) # df.Aでも可能
2013-01-01 0.166328
2013-01-02 -0.346681
2013-01-03 0.305456
2013-01-04 -0.788086
2013-01-05 -0.503083
2013-01-06 0.299511
Freq: D, Name: A, dtype: float64
# インデックス方向に対してスライスで取得
# インデックスの位置やラベルでの指定が可能
display(df[0:3])
display(df["20130102":"20130104"])
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.166328 | -2.136717 | -1.079066 | 0.412360 |
2013-01-02 | -0.346681 | -0.426526 | 0.518986 | -0.608594 |
2013-01-03 | 0.305456 | -0.382561 | 0.723871 | -0.209471 |
A | B | C | D | |
---|---|---|---|---|
2013-01-02 | -0.346681 | -0.426526 | 0.518986 | -0.608594 |
2013-01-03 | 0.305456 | -0.382561 | 0.723871 | -0.209471 |
2013-01-04 | -0.788086 | 0.588946 | 1.426202 | 0.289746 |
ラベル指定で取得#
DataFrameの loc
プロパティ、at
プロパティによって、ラベル指定によるデータ取得ができます。
DataFrame.loc
(詳細は公式ページ)
DataFrame.at
(詳細は公式ページ)
# 特定インデックスの取得
display(df.loc[dates[0]]) # dates[0] = '20130101'
A 0.166328
B -2.136717
C -1.079066
D 0.412360
Name: 2013-01-01 00:00:00, dtype: float64
# 特定インデックス・カラムの取得
display(df.loc[:, ["A", "B"]])
display(df.loc["20130102":"20130104", ["A", "B"]])
display(df.loc["20130102", ["A", "B"]])
display(df.loc[dates[0], "A"])
A | B | |
---|---|---|
2013-01-01 | 0.166328 | -2.136717 |
2013-01-02 | -0.346681 | -0.426526 |
2013-01-03 | 0.305456 | -0.382561 |
2013-01-04 | -0.788086 | 0.588946 |
2013-01-05 | -0.503083 | 0.567122 |
2013-01-06 | 0.299511 | -1.941320 |
A | B | |
---|---|---|
2013-01-02 | -0.346681 | -0.426526 |
2013-01-03 | 0.305456 | -0.382561 |
2013-01-04 | -0.788086 | 0.588946 |
A -0.346681
B -0.426526
Name: 2013-01-02 00:00:00, dtype: float64
0.16632787659365253
# 特定の1要素をラベル指定で取得する場合は、atの方が高速
display(df.at[dates[0], "A"])
0.16632787659365253
位置指定で取得#
DataFrameの iloc
プロパティ、iat
プロパティによって、位置指定によるデータ取得ができます。
DataFrame.iloc
(詳細は公式ページ)
DataFrame.iat
(詳細は公式ページ)
# 特定行の取得
display(df.iloc[3])
A -0.788086
B 0.588946
C 1.426202
D 0.289746
Name: 2013-01-04 00:00:00, dtype: float64
# 特定行・列の取得
display(df.iloc[3:5, 0:2])
display(df.iloc[[1, 2, 4], [0, 2]])
display(df.iloc[1:3, :])
display(df.iloc[:, 1:3])
display(df.iloc[1, 1])
A | B | |
---|---|---|
2013-01-04 | -0.788086 | 0.588946 |
2013-01-05 | -0.503083 | 0.567122 |
A | C | |
---|---|---|
2013-01-02 | -0.346681 | 0.518986 |
2013-01-03 | 0.305456 | 0.723871 |
2013-01-05 | -0.503083 | 1.287743 |
A | B | C | D | |
---|---|---|---|---|
2013-01-02 | -0.346681 | -0.426526 | 0.518986 | -0.608594 |
2013-01-03 | 0.305456 | -0.382561 | 0.723871 | -0.209471 |
B | C | |
---|---|---|
2013-01-01 | -2.136717 | -1.079066 |
2013-01-02 | -0.426526 | 0.518986 |
2013-01-03 | -0.382561 | 0.723871 |
2013-01-04 | 0.588946 | 1.426202 |
2013-01-05 | 0.567122 | 1.287743 |
2013-01-06 | -1.941320 | 1.391943 |
-0.4265262397519023
# 特定の1要素を位置指定で取得する場合は、iatの方が高速
display(df.iat[1, 1])
-0.4265262397519023
Booleanで取得#
# あるカラムに対するBooleanで取得
# ここでは、dfのAカラムの値が0より大きいインデックスのみを抽出
display(df["A"] > 0)
display(df[df["A"] > 0])
2013-01-01 True
2013-01-02 False
2013-01-03 True
2013-01-04 False
2013-01-05 False
2013-01-06 True
Freq: D, Name: A, dtype: bool
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.166328 | -2.136717 | -1.079066 | 0.412360 |
2013-01-03 | 0.305456 | -0.382561 | 0.723871 | -0.209471 |
2013-01-06 | 0.299511 | -1.941320 | 1.391943 | 1.173333 |
# DataFrame全体に対するBooleanで取得
# ここでは、dfの0より大きい要素のみ値を抽出
display(df > 0)
display(df[df > 0])
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | True | False | False | True |
2013-01-02 | False | False | True | False |
2013-01-03 | True | False | True | False |
2013-01-04 | False | True | True | True |
2013-01-05 | False | True | True | False |
2013-01-06 | True | False | True | True |
A | B | C | D | |
---|---|---|---|---|
2013-01-01 | 0.166328 | NaN | NaN | 0.412360 |
2013-01-02 | NaN | NaN | 0.518986 | NaN |
2013-01-03 | 0.305456 | NaN | 0.723871 | NaN |
2013-01-04 | NaN | 0.588946 | 1.426202 | 0.289746 |
2013-01-05 | NaN | 0.567122 | 1.287743 | NaN |
2013-01-06 | 0.299511 | NaN | 1.391943 | 1.173333 |
要素の追加・置換#
# Seriesを作成
s1 = pd.Series([1, 2, 3, 4, 5, 6], index=pd.date_range("20130102", periods=6))
display(s1)
# 作成したSeriesを新たにdfのFカラムとして追加(インデックスが合致する部分のみ)
df["F"] = s1
# dfの0行1列目の要素を0に置換
df.iat[0, 1] = 0
# dfのDカラムの要素をすべて5で置換
df.loc[:, "D"] = np.array([5] * len(df))
display(df)
2013-01-02 1
2013-01-03 2
2013-01-04 3
2013-01-05 4
2013-01-06 5
2013-01-07 6
Freq: D, dtype: int64
A | B | C | D | F | |
---|---|---|---|---|---|
2013-01-01 | 0.166328 | 0.000000 | -1.079066 | 5 | NaN |
2013-01-02 | -0.346681 | -0.426526 | 0.518986 | 5 | 1.0 |
2013-01-03 | 0.305456 | -0.382561 | 0.723871 | 5 | 2.0 |
2013-01-04 | -0.788086 | 0.588946 | 1.426202 | 5 | 3.0 |
2013-01-05 | -0.503083 | 0.567122 | 1.287743 | 5 | 4.0 |
2013-01-06 | 0.299511 | -1.941320 | 1.391943 | 5 | 5.0 |
欠損データの処理#
本章では、欠損データの処理方法を紹介します。紹介する内容は以下の通りです。
欠損データの削除
欠損データの置換
欠損データ位置の検索
欠損データの削除#
Series、DataFrameの dropna()
メソッドによって欠損データを削除することができます。さまざまな引数がありますが、ここでは主要なもののみを紹介します。
DataFrame.dropna(axis=0, how='any')
(詳細は公式ページ)
axis
: 要素を削除する軸を選択(デフォルトはインデックス方向)how
: 削除方法をany
、all
から選択(デフォルトはany
)any
: 一つでも欠損データがあれば対象インデックス/カラムを削除all
: すべてが欠損データであれば対象インデックス/カラムを削除
# 欠損を含むデータの作成
df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ["E"])
df1.loc[dates[0] : dates[1], "E"] = 1
display(df1)
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2013-01-01 | 0.166328 | 0.000000 | -1.079066 | 5 | NaN | 1.0 |
2013-01-02 | -0.346681 | -0.426526 | 0.518986 | 5 | 1.0 | 1.0 |
2013-01-03 | 0.305456 | -0.382561 | 0.723871 | 5 | 2.0 | NaN |
2013-01-04 | -0.788086 | 0.588946 | 1.426202 | 5 | 3.0 | NaN |
# 欠損データの削除
# 欠損が含まれるインデックスを削除
display(df1.dropna(how="any"))
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2013-01-02 | -0.346681 | -0.426526 | 0.518986 | 5 | 1.0 | 1.0 |
欠損データの置換#
Series、DataFrameの fillna()
メソッドによって欠損データを任意の値で置換することができます。さまざまな引数がありますが、ここでは主要なもののみを紹介します。
DataFrame.fillna(value=None, method=None)
(詳細は公式ページ)
value
: 置換する値を設定method
: 置換方法をbfill
、ffill
などから選択bfill
: 前の要素と同じ値で置換ffill
: 後の要素と同じ値で置換
# 欠損データを任意の値で置換
display(df1.fillna(value=5))
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2013-01-01 | 0.166328 | 0.000000 | -1.079066 | 5 | 5.0 | 1.0 |
2013-01-02 | -0.346681 | -0.426526 | 0.518986 | 5 | 1.0 | 1.0 |
2013-01-03 | 0.305456 | -0.382561 | 0.723871 | 5 | 2.0 | 5.0 |
2013-01-04 | -0.788086 | 0.588946 | 1.426202 | 5 | 3.0 | 5.0 |
欠損データ位置の検索#
pandasの isna()
関数によって欠損データ位置を True
、その他を False
とするDataFrameを取得することができます。
pandas.isna()
(詳細は公式ページ)
# 欠損データ位置の検索
display(pd.isna(df1))
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2013-01-01 | False | False | False | False | True | False |
2013-01-02 | False | False | False | False | False | False |
2013-01-03 | False | False | False | False | False | True |
2013-01-04 | False | False | False | False | False | True |
データの操作#
本章では、データの操作方法を紹介します。紹介する内容は以下の通りです。
統計量の算出
データ変換
度数算出
統計量の算出#
Series、DataFrameには要素の統計量を算出するさまざまなメソッドが存在します。
DataFrame.mean(axis=0)
: 平均値を算出DataFrame.std(axis=0)
: 標準偏差を算出DataFrame.var(axis=0)
: 分散を算出DataFrame.sum(axis=0)
: 合計値を算出DataFrame.min(axis=0)
: 最小値を抽出DataFrame.max(axis=0)
: 最大値を抽出DataFrame.median(axis=0)
: 中央値を抽出DataFrame.mode(axis=0)
: 最頻値を抽出
なお、デフォルトはカラム方向に統計量を算出しますが、 axis=1
とすると、インデックス方向に統計量を算出します。
# 平均値の算出
display(df.mean()) # デフォルトはカラムに対する平均値となる
A -0.144426
B -0.265723
C 0.711613
D 5.000000
F 3.000000
dtype: float64
display(df.mean(axis=1)) # axis=1とするとインデックスに対する平均値となる
2013-01-01 1.021815
2013-01-02 1.149156
2013-01-03 1.529353
2013-01-04 1.845412
2013-01-05 2.070356
2013-01-06 1.950027
Freq: D, dtype: float64
データ変換#
Series、DataFrameの apply()
メソッドによって任意の関数でデータを変換することができます。さまざまな引数がありますが、ここでは主要なもののみを紹介します。
DataFrame.apply(func, axis=0)
(詳細は公式ページ)
func
: 変換関数を指定axis
: 関数を適用する軸を選択(デフォルトはインデックス方向)
# NumPyの関数をデータし変換
display(df.apply(np.cumsum)) # NumPyのcumsum関数(累積和算出)を適用
A | B | C | D | F | |
---|---|---|---|---|---|
2013-01-01 | 0.166328 | 0.000000 | -1.079066 | 5 | NaN |
2013-01-02 | -0.180353 | -0.426526 | -0.560081 | 10 | 1.0 |
2013-01-03 | 0.125104 | -0.809087 | 0.163791 | 15 | 3.0 |
2013-01-04 | -0.662982 | -0.220142 | 1.589992 | 20 | 6.0 |
2013-01-05 | -1.166065 | 0.346980 | 2.877736 | 25 | 10.0 |
2013-01-06 | -0.866554 | -1.594340 | 4.269679 | 30 | 15.0 |
# ユーザーが定義した関数も適用可能
display(df.apply(lambda x: x.max() - x.min())) # カラムごとに最大値と最小値の差を算出
A 1.093542
B 2.530266
C 2.505268
D 0.000000
F 4.000000
dtype: float64
度数算出#
Seriesの value_counts()
メソッドによって含まれる各要素の度数を算出できます。
Series.value_counts()
(詳細は公式ページ)
# カラムごとにユニークな要素の度数を算出する
s = pd.Series(np.random.randint(0, 7, size=10))
display(s)
display(s.value_counts())
0 3
1 6
2 4
3 2
4 3
5 5
6 1
7 4
8 6
9 3
dtype: int64
3 3
6 2
4 2
5 1
2 1
1 1
dtype: int64
データの結合#
本章では、データの結合方法を紹介します。紹介する内容は以下の通りです。
Concat
Join
Concat#
pandasの concat()
関数によって、複数のpandasオブジェクト(Series、DataFrame)を連結できます。さまざまな引数がありますが、ここでは主要なもののみを紹介します。
pandas.concat(objs, axis=0, ignore_index=True)
(詳細は公式ページ)
objs
: 連結するpandasオブジェクトをまとめたものaxis
: pandasオブジェクトを連結する方向(デフォルトはインデックス方向)ignore_index
: 連結前のインデックスを保持するかを設定(デフォルトは保持する、True
orFalse
)True
: インデックスを新たに振り直す(先頭から0、1、2、、、)False
: 連結前のインデックスを保持する
# 複数のpandasオブジェクト(Series、DataFrame)を連結
# まず、適当なDataFrameを作成
df = pd.DataFrame(np.random.randn(10, 4))
display(df)
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 0.806613 | -1.919551 | 0.010989 | -1.386274 |
1 | -0.485257 | -0.867472 | -0.452377 | -0.100792 |
2 | -0.555209 | -1.594025 | 0.094861 | -0.921013 |
3 | 1.815996 | 0.445259 | 0.002511 | 0.950379 |
4 | -1.045618 | -0.510390 | 0.739795 | 0.220217 |
5 | 1.089392 | 0.054136 | 0.793023 | -0.614540 |
6 | -0.448433 | 0.869446 | -1.101350 | 0.500749 |
7 | -0.258171 | 0.971561 | 0.417669 | 0.253375 |
8 | -0.099999 | 0.200793 | -0.153091 | -0.254538 |
9 | 0.080026 | 0.231965 | 1.085134 | -0.841865 |
# 作成したDataFrameを適当に分割し、listに格納
pieces = [df[:3], df[3:7], df[7:]]
display(pieces)
[ 0 1 2 3
0 0.806613 -1.919551 0.010989 -1.386274
1 -0.485257 -0.867472 -0.452377 -0.100792
2 -0.555209 -1.594025 0.094861 -0.921013,
0 1 2 3
3 1.815996 0.445259 0.002511 0.950379
4 -1.045618 -0.510390 0.739795 0.220217
5 1.089392 0.054136 0.793023 -0.614540
6 -0.448433 0.869446 -1.101350 0.500749,
0 1 2 3
7 -0.258171 0.971561 0.417669 0.253375
8 -0.099999 0.200793 -0.153091 -0.254538
9 0.080026 0.231965 1.085134 -0.841865]
# listに格納されたDataFrameを、インデックス方向に連結
display(pd.concat(pieces))
0 | 1 | 2 | 3 | |
---|---|---|---|---|
0 | 0.806613 | -1.919551 | 0.010989 | -1.386274 |
1 | -0.485257 | -0.867472 | -0.452377 | -0.100792 |
2 | -0.555209 | -1.594025 | 0.094861 | -0.921013 |
3 | 1.815996 | 0.445259 | 0.002511 | 0.950379 |
4 | -1.045618 | -0.510390 | 0.739795 | 0.220217 |
5 | 1.089392 | 0.054136 | 0.793023 | -0.614540 |
6 | -0.448433 | 0.869446 | -1.101350 | 0.500749 |
7 | -0.258171 | 0.971561 | 0.417669 | 0.253375 |
8 | -0.099999 | 0.200793 | -0.153091 | -0.254538 |
9 | 0.080026 | 0.231965 | 1.085134 | -0.841865 |
Join#
DataFrameの join()
メソッドによって、あるDataFrameと別のpandasオブジェクトをSQL-likeに連結できます。さまざまな引数がありますが、ここでは主要なもののみを紹介します。
DataFrame.concat(other, on=None, how='left')
(詳細は公式ページ)
other
: 連結対象のpandasオブジェクト(Series、DataFrame)on
: キーとするカラム名を設定how
: データの連結方法の選択(デフォルトはleft
、left
orright
orouter
orinner
)それぞれの連結イメージはこちらのサイトがわかりやすいです。
# SQL-likeにデータを結合することも可能
left = pd.DataFrame({"key": ["foo", "foo"], "lval": [1, 2]})
right = pd.DataFrame({"key": ["foo", "foo"], "rval": [4, 5]})
display(left)
display(right)
display(pd.merge(left, right, on="key"))
key | lval | |
---|---|---|
0 | foo | 1 |
1 | foo | 2 |
key | rval | |
---|---|---|
0 | foo | 4 |
1 | foo | 5 |
key | lval | rval | |
---|---|---|---|
0 | foo | 1 | 4 |
1 | foo | 1 | 5 |
2 | foo | 2 | 4 |
3 | foo | 2 | 5 |
# もう一例紹介
left = pd.DataFrame({"key": ["foo", "bar"], "lval": [1, 2]})
right = pd.DataFrame({"key": ["foo", "bar"], "rval": [4, 5]})
display(left)
display(right)
display(pd.merge(left, right, on="key"))
key | lval | |
---|---|---|
0 | foo | 1 |
1 | bar | 2 |
key | rval | |
---|---|---|
0 | foo | 4 |
1 | bar | 5 |
key | lval | rval | |
---|---|---|---|
0 | foo | 1 | 4 |
1 | bar | 2 | 5 |
グルーピング#
本章では、データのグルーピング方法を紹介します。データをグルーピングし、各グループの特徴(例えば統計量など)を簡単に算出することができます。
具体的には、DataFrameの groupby()
メソッド(詳細は公式ページ)によってグルーピングを簡単に行うことができます。グルーピング処理は以下の手順で行われます。
データを任意の基準に従って分割
分割したデータグループそれぞれに対し、任意の関数を適用
関数を適用した結果を結合
# まず、適当なDataFrameを作成
df = pd.DataFrame(
{
"A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "bar"],
"B": ["one", "one", "two", "three", "two", "two", "one", "three"],
"C": np.random.randn(8),
"D": np.random.randn(8),
}
)
display(df)
A | B | C | D | |
---|---|---|---|---|
0 | foo | one | 0.687179 | -0.717884 |
1 | bar | one | 3.079297 | 0.699311 |
2 | foo | two | -1.566509 | -0.491073 |
3 | bar | three | 1.063598 | 0.943438 |
4 | foo | two | -1.060167 | 0.795170 |
5 | bar | two | 0.750331 | 1.370753 |
6 | foo | one | 0.271376 | -0.181413 |
7 | bar | three | -0.942895 | -0.207787 |
# データをカラムAの要素に従ってグルーピングし、それぞれの合計値を算出
display(df.groupby("A").sum())
C | D | |
---|---|---|
A | ||
bar | 3.950331 | 2.805715 |
foo | -1.668122 | -0.595200 |
# 複数カラムを指定することも可能
display(df.groupby(["A", "B"]).sum())
C | D | ||
---|---|---|---|
A | B | ||
bar | one | 3.079297 | 0.699311 |
three | 0.120703 | 0.735651 | |
two | 0.750331 | 1.370753 | |
foo | one | 0.958555 | -0.899297 |
two | -2.626676 | 0.304097 |
時系列データの処理#
本章では、時系列データの処理方法を紹介します。なお、時系列データの定義は DatetimeIndex
を持つpandasオブジェクト(Series、DataFrame)とします。DatetimeIndex
を持つことで、データのリサンプリングなどを簡単に実施することができます。
# まず、適当な時系列データを作成
rng = pd.date_range("1/1/2012", periods=100, freq="S")
ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
display(ts)
2012-01-01 00:00:00 185
2012-01-01 00:00:01 292
2012-01-01 00:00:02 261
2012-01-01 00:00:03 493
2012-01-01 00:00:04 180
...
2012-01-01 00:01:35 153
2012-01-01 00:01:36 300
2012-01-01 00:01:37 84
2012-01-01 00:01:38 41
2012-01-01 00:01:39 73
Freq: S, Length: 100, dtype: int64
# 時系列データを任意の時間間隔とする
# ここでは、5分間隔で再集計し、その合計値を要素として扱う
display(ts.resample("5Min").sum())
2012-01-01 23810
Freq: 5T, dtype: int64
# タイムゾーンの設定・変更も可能
rng = pd.date_range("3/6/2012 00:00", periods=5, freq="D")
ts = pd.Series(np.random.randn(len(rng)), rng)
display(ts)
2012-03-06 -0.301987
2012-03-07 0.390751
2012-03-08 0.900278
2012-03-09 -1.092933
2012-03-10 -1.899672
Freq: D, dtype: float64
# UTC(協定世界時)に設定
ts_utc = ts.tz_localize("UTC")
display(ts_utc)
2012-03-06 00:00:00+00:00 -0.301987
2012-03-07 00:00:00+00:00 0.390751
2012-03-08 00:00:00+00:00 0.900278
2012-03-09 00:00:00+00:00 -1.092933
2012-03-10 00:00:00+00:00 -1.899672
Freq: D, dtype: float64
# US/Eastern(アメリカ東部標準時)に変換(UTC - 5時間)
display(ts_utc.tz_convert("US/Eastern"))
2012-03-05 19:00:00-05:00 -0.301987
2012-03-06 19:00:00-05:00 0.390751
2012-03-07 19:00:00-05:00 0.900278
2012-03-08 19:00:00-05:00 -1.092933
2012-03-09 19:00:00-05:00 -1.899672
Freq: D, dtype: float64
# さまざまな時間表現が可能
# yyyy-mm-dd
rng = pd.date_range("1/1/2012", periods=5, freq="M")
ts = pd.Series(np.random.randn(len(rng)), index=rng)
display(ts)
2012-01-31 0.959458
2012-02-29 0.295099
2012-03-31 0.665237
2012-04-30 0.115700
2012-05-31 1.622997
Freq: M, dtype: float64
# yyyy-mm
ps = ts.to_period()
display(ps)
2012-01 0.959458
2012-02 0.295099
2012-03 0.665237
2012-04 0.115700
2012-05 1.622997
Freq: M, dtype: float64
# yyyy-mm-01
display(ps.to_timestamp())
2012-01-01 0.959458
2012-02-01 0.295099
2012-03-01 0.665237
2012-04-01 0.115700
2012-05-01 1.622997
Freq: MS, dtype: float64
# 四半期単位での時間表現も可能
prng = pd.period_range("1990Q1", "2000Q4", freq="Q-NOV")
ts = pd.Series(np.random.randn(len(prng)), prng)
ts.index = (prng.asfreq("M", "e") + 1).asfreq("H", "s") + 9
display(ts.head())
1990-03-01 09:00 1.182331
1990-06-01 09:00 -0.538331
1990-09-01 09:00 -0.279225
1990-12-01 09:00 -0.286005
1991-03-01 09:00 0.897384
Freq: H, dtype: float64
データの可視化#
本章では、データの可視化方法を紹介します。pandasの可視化メソッドはMatplotlibのラッパーであり、Matplotlibよりも簡易に可視化を行うことができます。
基本的に、Series、DataFrameの plot()
メソッドを使うことで可視化を行うことができます。
折れ線グラフによる可視化を紹介しますが、ほかにも散布図や箱ひげ図など、さまざまな可視化を行うことができます。(詳細はこちらのサイト)
# pandasの可視化メソッドを使うために、matplotlibをインポート
import matplotlib.pyplot as plt
%matplotlib inline
# ランダムウォークする時系列データを作成
ts = pd.Series(np.random.randn(1000), index=pd.date_range("1/1/2000", periods=1000))
ts = ts.cumsum()
ts.plot() # Series.plot()により、インデックスをx軸、要素をy軸とした折れ線グラフを作成できる
<matplotlib.axes._subplots.AxesSubplot at 0x11a7f9790>

# 4つのランダムウォークする時系列データを作成
df = pd.DataFrame(
np.random.randn(1000, 4), index=ts.index, columns=["A", "B", "C", "D"]
)
df = df.cumsum()
plt.figure()
df.plot() # DataFrame.plot()によりインデックスをx軸、各カラム要素をy軸とした折れ線グラフを作成できる
plt.legend(loc="best")
<matplotlib.legend.Legend at 0x11a600c90>
<Figure size 432x288 with 0 Axes>

データの書き出し・読み込み#
本章では、データの書き出し・読み込み方法を紹介します。紹介する内容は以下の通りです
CSV
Excel
CSV形式#
Series、DataFrameの to_csv()
メソッドによってCSV形式での書き込みが、pandasの read_csv()
関数によってCSV形式データの読み込みができます。それぞれさまざまな引数が存在しますが、ここでは主要なもののみを紹介します。
DataFrame.to_csv(path=None, columns=None, index=True)
(詳細は公式ページ)
path
: 書き出し先のファイルパス(str
など)columns
: 書き出し対象のカラムを設定(str
やint
など、list
での設定が可能)index
: 行番号を書き出すかを選択(デフォルトは書き出す、True
orFalse
)
pandas.read_csv(filepath, index_col=None, usecols, parse_dates=False)
(詳細は公式ページ)
filepath
: 読み込み対象のCSVファイルパス(str
など)index_col
: インデックスとしたカラムを設定(str
やint
など、list
での設定が可能)usecols
: 読み込みたいカラムを設定(str
やint
など、list
での設定が可能)parse_dates
:Datetime
としたいカラムを設定(str
やint
など、list
での設定が可能)
# csv形式でのデータ書き込み
df.to_csv("foo.csv")
# csv形式データの読み込み
display(pd.read_csv("foo.csv"))
Unnamed: 0 | A | B | C | D | |
---|---|---|---|---|---|
0 | 2000-01-01 | 1.943932 | -0.208172 | 0.173399 | -0.877959 |
1 | 2000-01-02 | 3.790965 | -0.575836 | 0.731849 | -1.050896 |
2 | 2000-01-03 | 4.994910 | -2.211932 | 0.825693 | -1.890958 |
3 | 2000-01-04 | 5.541881 | 0.112860 | -0.357612 | -2.818091 |
4 | 2000-01-05 | 5.767437 | 0.372435 | -2.124310 | -2.179938 |
... | ... | ... | ... | ... | ... |
995 | 2002-09-22 | -27.517641 | 14.537824 | -33.377617 | -42.739328 |
996 | 2002-09-23 | -29.672076 | 14.115574 | -33.633798 | -44.358625 |
997 | 2002-09-24 | -30.274690 | 12.876268 | -32.796361 | -44.547047 |
998 | 2002-09-25 | -29.809977 | 12.402727 | -33.746257 | -45.242380 |
999 | 2002-09-26 | -29.891825 | 12.262031 | -34.786199 | -45.565377 |
1000 rows × 5 columns
Excel形式#
Series、DataFrameの to_excel()
メソッドによってExcel形式での書き込みが、pandasの read_excel()
関数によってExcel形式データの読み込みができます。それぞれさまざまな引数が存在しますが、ここでは主要なもののみを紹介します。
DataFrame.to_excel(excel_writer, sheet_name='Sheet1')
(詳細は公式ページ)
excel_writer
: 書き出し先のファイルパス(str
)sheet_name
: 書き出し先シートを設定(str
)
pandas.read_excel(io, sheet_name=0)
(詳細は公式ページ)
io
: 読み込み対象のExcelファイルパス(str
)sheet_name
: インデックスとしたカラムを設定(str
やint
など、list
での設定が可能)
# excel形式でのデータ書き込み
df.to_excel("foo.xlsx", sheet_name="sheet1")
# excel形式データの読み込み
display(pd.read_excel("foo.xlsx", "sheet1", index_col=None, na_values=["NA"]))
Unnamed: 0 | A | B | C | D | |
---|---|---|---|---|---|
0 | 2000-01-01 | 1.943932 | -0.208172 | 0.173399 | -0.877959 |
1 | 2000-01-02 | 3.790965 | -0.575836 | 0.731849 | -1.050896 |
2 | 2000-01-03 | 4.994910 | -2.211932 | 0.825693 | -1.890958 |
3 | 2000-01-04 | 5.541881 | 0.112860 | -0.357612 | -2.818091 |
4 | 2000-01-05 | 5.767437 | 0.372435 | -2.124310 | -2.179938 |
... | ... | ... | ... | ... | ... |
995 | 2002-09-22 | -27.517641 | 14.537824 | -33.377617 | -42.739328 |
996 | 2002-09-23 | -29.672076 | 14.115574 | -33.633798 | -44.358625 |
997 | 2002-09-24 | -30.274690 | 12.876268 | -32.796361 | -44.547047 |
998 | 2002-09-25 | -29.809977 | 12.402727 | -33.746257 | -45.242380 |
999 | 2002-09-26 | -29.891825 | 12.262031 | -34.786199 | -45.565377 |
1000 rows × 5 columns
小括#
本稿ではデータ分析で頻出のpandasの基本操作について、公式チュートリアルをベースに紹介しました。pandasにはここでは紹介しきれなかったさまざまな便利機能がまだまだ存在します。データを弄る際、まずはpandasの機能でどうにかならないか検索してみることをお勧めします。