Pandas 練習ノート

Pandas のオンラインドキュメントに,"Getting started" というページがあります.そのなかに "Intro to pandas" というセクションがあり,Pandas の機能が紹介されています.

このページでは,"Getting started" のページからリンクされている "Intro to pandas" と "10 minutes to pandas" を,API リファレンスを参照しながら少しだけ HTML に記してみます.

Pandas には NumPy API が使われています.私は,Pandas を学ぶ前に少しだけ NumPy を学んでおきました(NumPy 練習ノート).

インフォメーション

オンラインドキュメント

Debian パッケージ

このページは,Debian GNU/Linux バージョン 13 "trixie" で作成しました.
インストールしている主なパッケージを示します.

パッケージ名(バージョン)
python3 (3.13.5)対話式の高レベルオブジェクト指向言語(このページ改定開始前にインストール済みでした)
python3-pandas (2.2.3)データ分析をするためのパッケージ.リレーショナルデータを扱う DataFrame クラスと ラベル付きデータを扱うための Seried クラスがあります
python-pandas-doc (2.2.3)HTML ドキュメントが /usr/share/doc/python-pandas-doc/html/ 以下にインストールされました

目次(ページ内リンク)

目次として,"10 minutes to pandas" のパラグラフのタイトルと,このページのセクションへのリンクとを対応付けてみました.

  1. Basic data structures in pandas:基本データ構造
  2. Object creation:Series のインスタンス化DataFrame のインスタンス化
  3. Viewing data:データの表示
  4. selectio:データフレームでの選択
  5. missing_data
  6. operations
  7. merge
  8. grouping
  9. reshaping
  10. time_series
  11. categoricals
  12. plotting
  13. Importing_exporting
  14. gotchas

Pandas の基本データ構造

"Basic data structures in pandas" を読むと,Pandas には,データ処理をおこなうためのクラスが 2 個あると書いてあります.
(書いてあって,API リファレンスへのリンクが張ってあるだけです)

DataFrame の API リファレンスを眺める

上のリンクから,より頻用するであろう DataFrame の API リファレンスのトップページに移動すると,以下の構成となっています.
コンストラクタでインスタンス化の方法を学んで,サンプルコードで簡単な使い方を理解して,細かいことはアトリビュートやメソッドを見れば良さそうです.

  1. クラス宣言とコンストラクタ引数
  2. 対話形式でのサンプルコード
  3. アトリビュート
  4. メソッド

アトリビュートとは,別の言語でいうと,公開メンバ変数とかプロパティに該当するのでしょうか.すなわち, "." 演算子でアクセスでき,かつ () でパラメータを渡さないオブジェクトです.
イメージするために最初の 5 個を列挙してみます.

  1. T:転置.調べないと判りませんが,コンストラクタで作成されるのでしょうか?
  2. at:格納されている値.[] 演算子で行と列を指定します
  3. attrs:Dictionary of global attributes of this dataset.今の私にはイメージしにくいので,今後の課題とします
  4. axes:データフレームの軸を表すリスト
  5. columns:データフレームの列ラベル

Series のインスタンス化

Series は,種々のデータ型を格納する一次元のラベル付き配列です.
このパラグラフでは,"10 minutes to pandas" の最初の例をソースファイルの形に書き換えます.

ライブラリのインポート

ライブラリ numpy および pandas は通常,このソースコードのようにインクルードします.
NumPy のページに記されている説明を改変すれば,「広く採用されている慣例で,Pandas を使ったコードを読みやすくするために,インポートする名前を pd と短くします」とか,「常に import pandas as pd を使用することをお勧めします」となるのでしょう.


import numpy as np
import pandas as pd

ソースコード

下にソースコードを示します.
Series のコンストラクタ引数として値のリスト([1, 3…])を渡しています.他の引数は省略しているのでデフォルト値が使われます.
np.nan は非数(Not a Number)のことですが,NumPy のオブジェクトを使っています.そのため numpy もインポートする必要があります.

ソースコード

ここでは,main.py という名前で保存することにします.


import numpy as np
import pandas as pd

s = pd.Series([1, 3, 5, np.nan, 6, 8])
print(s)

実行してみる

main.py という Python スクリプトを実行するには,端末に,
$ python3 main.py
と入力するのでした.結果,次のように表示されました.

下が実行結果です.インデックス,値,および dtype というものが出力されました.
dtype は Numpy のデータ型です.Pandas ではそれをそのまま使っているようです.

0    1.0
1    3.0
2    5.0
3    NaN
4    6.0
5    8.0
dtype: float64

Series のクラス宣言

API リファレンスで pandas.Seriesを見ると,次のように書いてあります.


class pandas.Series(data=None, index=None, dtype=None, name=None, copy=None, fastpath=<no_default>)

コンストラクタパラメータはそれぞれ,

data : array-like, Iterable, dict, or scalar value
作成される Series インスタンスの元となるデータ.Python のリストなど.

index : array-like or Index (1d)
デフォルト 値は RangeIndex (0, 1, 2, …, n)です .index が省略された場合,data が辞書型であれば,キーが index となります.

dtype : str, numpy.dtype, or ExtensionDtype, optional
データ型です指定しない場合は data から推測されます.Series の要素のデータ型は,NumPy の dtype を利用しています.

name : Hashable, default None
Series の名前(現時点では解りませんが,Series を束ねて DataFrame を作成した際に列名として使うとかでしょうか).

copy : bool, default False
data のコピーを作成するか参照とするかを設定します.デフォルト値は false.

fastpath : 説明は記述されていません
現時点では使い方が解りません.ソースコードを見ると bool 値のようです.

API リファレンスの最初の例

ソースファイルの形にすると次のようになります.
第一パラメータ data に辞書型配列を渡しています.この場合,第二パラメーの index は省略しても,data のキーが index になるはずです.


import numpy as np
import pandas as pd

d = {'a': 1, 'b': 2, 'c': 3}
ser = pd.Series(data=d, index=['a', 'b', 'c'])  #ser = pd.Series(data=d)  でも同じ動作になるはず
print(ser)

実行すると,

a    1
b    2
c    3
dtype: int64

第二パラメーを省略してみたら,期待どおり同じ結果になりました.


DataFrame のインスタンス化

DataFrame は,種々のデータ型を二次元配列のように格納する,行と列からなるデータ構造です.
"10 minutes to pandas" には DataFrame の作成例がいくつか紹介されているのですが,最初の例を参考にしてコーディングしてみます.

ソースコード


import numpy as np
import pandas as pd

dates = pd.date_range("20130101", periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list("ABCD"))
print(df)

ここで作成している DataFrame df の行ラベルと値は,具体的な値を記述するのではなく,メソッドを使って作成しています.読みにくくなりそうなので,これらのメソッドについては,API リファレンスへのリンクを張るにとどめます.

実行結果

下は,実行したときの出力の一例です.

                   A         B         C         D
2013-01-01  1.136817  0.193710 -0.132566  2.237783
2013-01-02  0.068851 -0.187624 -0.774221  1.061339
2013-01-03  0.266911 -0.684776 -2.650970  0.921205
2013-01-04  0.653107 -0.608141 -0.259438 -0.822131
2013-01-05  0.980141  1.926887 -1.075509 -0.864783
2013-01-06  0.429613  1.478922 -2.663787 -0.106529

DataFrame のクラス宣言

DataFrame のクラス宣言を API リファレンスで見ると,


class pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=None)

コンストラクタ引数は,以下の意味です.

data : ndarray (structured or homogeneous), Iterable, dict, or DataFrame
dict には,系列,配列,定数,データ・クラス,リストのようなオブジェクトを含めることができるそうです.
あと,列の整列規則が記されています.

index : Index or array-like
生成する DataFrame に使用するインデックス.デフォルトは RangeIndex となります.

columns : Index or array-like
データに列ラベルが含まれていない場合に使われるラベルです.デフォルトは RangeIndex(0, 1, 2, ..., n).
データに列ラベルが含まれている場合は,代わりにそれで列選択を行います.

dtype : dtype, default None
データ型(Data type to force と書いてあります).単一のデータ型のみが可能です.省略した場合は data から推測されるようです.

copy : bool or None, default None
data をコピーするか参照にするか.
data が dict 型の場合,デフォルトの None は copy=True と動作します.data が DataFrame 型の場合,デフォルトの None は copy=False と動作します.


データの表示

データの表示に関わるメソッドとアトリビュート

以下のメソッドが紹介されています.各メソッドについて,引数を明瞭にしつつ,API リファレンスにリンクを張りました.

データの表示に関わるアトリビュート

"10 minutes to pandas" では,以下のアトリビュートが紹介されています.API リファレンスにリンクを張りました.

以下で,いくつかサンプルコードを書いてみます.

DataFrame.describe()

describe() メソッドは,デフォルトで,'numeric' データのみ,25, 50, 75 パーセンタイルで区分けしたデータが返されます.
API リファレンスにパラメータを設定するサンプルコードがあるので,それをソースファイルの形に改変して紹介します.


import pandas as pd
import numpy as np

#ここで,'categorical','numeric','object' というのは,単に列名です.
df = pd.DataFrame({'categorical': pd.Categorical(['d', 'e', 'f']),
                   'numeric': [1, 2, 3],
                   'object': ['a', 'b', 'c'] })

print(df)  #データフレーム全体を出力
#print(df.describe())  #統計諸量を出力.ここでは 'numeric' 列のみ出力されました.値を NaN とするとデータがないものとして計算されました
#print(df.describe(percentiles=[0.25, 0.5, 0.75]))  #パーセンタイルを指定して統計諸量を出力.コードのパラメータはデフォルト値
print(df.describe(include='all')) #すべての統計諸量が出力されます.数値に関わる部分は NaN となります
#print(df.describe(include=[np.number]))  #'number' 列で,NaN 以外の値が格納された行が出力されました
#print(df.describe(include=['category']))  #'category' 列で,NaN 以外の値が格納された行が出力されました
#print(df.describe(exclude=[np.number]))  #'number' 列以外の列で,NaN 以外の値が格納された行が出力されました
#print(df.describe(exclude=[object]))  #'number' 列以外の列のすべての行が出力されました

#複数のパラメータを指定する
#print(df.describe(percentiles=[0.2, 0.4, 0.6, 0.8], include='all'))  #include のオプションで 'numeric' 以外のデータも表示

実行結果を下に示します.
前半は print(df),後半が print(df.describe(include='all')) の出力です.

  categorical  numeric object
0           d        1      a
1           e        2      b
2           f        3      c
       categorical  numeric object
count            3      3.0      3
unique           3      NaN      3
top              d      NaN      a
freq             1      NaN      1
mean           NaN      2.0    NaN
std            NaN      1.0    NaN
min            NaN      1.0    NaN
25%            NaN      1.5    NaN
50%            NaN      2.0    NaN
75%            NaN      2.5    NaN
max            NaN      3.0    NaN

DataFrame.sort_values() のサンプルコード

ソートには sort_index() と sort_values() があります.ここでは,後者を練習してみます.
もう一度 API リファレンスのメソッド宣言を記すと,

まず,引数を整理します.API リファレンスを読みつつ解釈すると,

DataFrame.sort_values() のサンプルコード

種々の引数オプションを付けてコードを作成してみました.出典が判らなくなりました.
適宜,コメントアウト,コメントインしてください.


import pandas as pd
import numpy as np

df = pd.DataFrame(
 data={
    'col2': [4, 5, 6, 1, 2, 3],
    'col1': [6, 5, 4, 3, 2, 1],
    'col3': [2, 4, 6, 1, 3, np.nan]},
 index=['A', 'B', 'C', 'D', 'E', 'F']
)
print(df)
print()

#これらは DataFrame が戻り値
sorted = df.sort_values(by='col1')  #'col1' 列の大小関係に従って行を入れ替える
#sorted = df.sort_values(by='col1', axis=0)  #上と同じ'
#sorted = df.sort_values(by='A', axis=1)  #'A' 行の大小関係に従って列を入れ替える
#sorted = df.sort_values(by=['col1', 'col2']) 'col1' の大小関係にしたがって,ただし同値の場合は 'col2' の大小関係に従って行を入れ替える
#sorted = df.sort_values(by='col1', ascending=False)  #'col1' 列の大小関係に従って行を入れ替える.ただし,降順
#sorted = df.sort_values(by='col1', ignore_index=True)  #index を無視する.出力を見ると,1,2,3,… と行番号が振られていました
#sorted = df.sort_values(by='col3', na_position='first')  #'col3' 列の大小関係に従って行を入れ替える.ただし,np.NaN を先頭に置く
print(sorted)

#これは戻り値が None
#df.sort_values(by='col1', inplace=True)
#print(df)

データフレームでの選択

データを選択するアトリビュート

"10 minutes to pandas" のこのセクションの冒頭では,NumPy の構文は直感的で対話型の作業に便利としつつ,コードを作成する場合には Pandas のメソッドを使うことが推奨されています.
以下のアトリビュートが紹介されているのですが,API リファレンスを見ると DataFrame.iloc はバージョン 2.2.0 で廃止されたと記されています.
リンク先は API リファレンスです.

サンプルコード

ここでは,API リファレンスの at および iat に記されているサンプルコードを改変して紹介します.


import pandas as pd

df = pd.DataFrame(
    [[0, 2, 3], [0, 4, 1], [10, 20, 30]],
    index=[4, 5, 6],
    columns=['A', 'B', 'C'])
print(df)
print()

#at の利用例
print("df.at[4, 'B'] =", df.at[4, 'B'])
df.at[4, 'B'] = 10
print("df.at[4, 'B'] =", df.at[4, 'B'])

#iat の利用例
print("df.iat[1, 2] =", df.iat[1, 2])
df.iat[1, 2] = 10
print("df.iat[1, 2] =", df.iat[1, 2])
print()

#loc の利用例
print("df.loc[B] =", df.loc[B])

実行結果

下に実行結果を記します,

    A   B   C
4   0   2   3
5   0   4   1
6  10  20  30

df.at[4, 'B'] = 2
df.at[4, 'B'] = 10
df.iat[1, 2] = 1
df.iat[1, 2] = 10

df.loc[4] = A     0
B    10
C     3
Name: 4, dtype: int64