『Python数値計算ノート』ではアフィリエイトプログラムを利用して商品を紹介しています。

pandas.Series

pandas.Seriesの構造と作成方法

pandas の Series オブジェクトは NumPy の一次元配列に明示的なインデクス (ラベル) をマップする(割り当てる)構造体です。pandas.Series() にシーケンスまたは配列を渡すと Series オブジェクトが生成されます。

# PANDAS_SERIES

# In[1]

import numpy as np
import pandas as pd

# Seriesオブジェクトを生成
data = pd.Series([10, 20, 30])

print(data)
# 0    10
# 1    20
# 2    30
# dtype: int64

Series オブジェクトの左側の列に表示されている数字が Index オブジェクト とよばれる明示的インデクスで、index 属性にアクセスして取り出せます。

# In[2]

# dataのindex属性を取得
d_idx = data.index

print(d_idx)
# RangeIndex(start=0, stop=3, step=1)

Series オブジェクトの右側の列に並ぶ数字は NumPy の配列 (ndarray) です。values 属性にアクセスして参照できます。

# In[3]

# dataのvalues属性を取得
d_val = data.values

print(d_val)
print(type(d_val))

# [10 20 30]
# <class 'numpy.ndarray'>

Seriesのインデクス

SeriesのIndexオブジェクトは、NumPy 配列の内部インデクスとは別に定義されています。デフォルト設定では 0 から始まる整数がマップされていますが、ユーザーは index 引数にシーケンスや配列を渡してインデクスを自由に設定できます。Index オブジェクトは数値に限らず、文字列など任意の型で構成できます。

# PANDAS_SERIES_INDEX

# In[1]

# 配列に文字列をマップする
data = pd.Series([10, 20, 30, 40, 50],
                 index = ["a", "b", "c", "d", "e"])

print(data)
# a    10
# b    20
# c    30
# d    40
# e    50
# dtype: int64

Seriesオブジェクトの配列要素には、明示的なインデクスを使ってアクセスできます。

# In[2]

print(data["c"])
# 30

NumPy の配列と同様に、Seriesオブジェクトはスライシング、マスク、ファンシーインデクスなどの機能を備えています。

# In[3]

# インデクス b から d までスライシング
print(data["b" : "d"])

# b    20
# c    30
# d    40
# dtype: int64

# In[4]

# マスク(30以上の要素をすべて取得)
print(data[data >= 30])

# c    30
# d    40
# e    50
# dtype: int64

# In[5]

# ファンシーインデクス
idx = ["c", "b", "e"]

print(data[idx])
# c    30
# b    20
# e    50
# dtype: int64

Seriesとディクショナリの比較

Seriesオブジェクト は Python のディクショナリ (dictオブジェクト) に類似する構造体です。Indexオブジェクトはディクショナリの key、一次元配列はディクショナリの value と考えることができます。実際、pandas.Series() にディクショナリを渡すと そのままの形で Series オブジェクトに変換されます。

# PANDAS_SERIES_DICTIONARY

# In[1]

import numpy as np
import pandas as pd

# Python入門書の表題と価格
python_book_dict = {"かんたんPython" : 3002,
                    "Pythonスタートブック" : 2700,
                    "わかるPython" : 2570}

# 辞書をSeriesオブジェクトに変換
python_book = pd.Series(python_book_dict)

print(python_book)
# かんたんPython       3002
# Pythonスタートブック    2700
# わかるPython        2570
# dtype: int64

Seriesとスカラーの演算

算術演算子を使って Series オブジェクトとスカラー (数値) の間で演算を実行すると、オブジェクトの中に組み込まれた NumPy の一次元配列とスカラーの間で演算が実行され、インデクスはそのまま保存されます。簡単な例を見てみましょう。最初に次のような Seriesオブジェクトを生成します。

# PANDAS_SERIES_SCALAR

# In[1]

# NumPyとpandas をインポート
import numpy as np
import pandas as pd

# Seriesオブジェクトを生成
x = pd.Series([10, 20, 30],
              index = ["a", "b", "c"])

print(x)
# a    10
# b    20
# c    30
# dtype: int64

x + 5 は、すべての要素に 5 を加えます:

# In[2]

# すべての要素に5を加える
y = x + 5

print(y)
# a    15
# b    25
# c    35
# dtype: int64

2 * x はすべての要素を 2 倍します:

# In[3]

# すべての要素を2倍する
z = 2*x 

print(z)
# a    20
# b    40
# c    60
# dtype: int64

Seriesとユニバーサル関数

NumPy のユニバーサル関数 (ufunc) に Seriesオブジェクトを渡すと、インデクスをそのまま残します。

# In[4]

# すべての要素の自然対数をとる
y = np.log(x)

print(y)
# a    2.302585
# b    2.995732
# c    3.401197
# dtype: float64

Seriesのデータ操作

NumPy配列と同じように、Seriesオブジェクト同士で算術演算子やメソッドを用いた演算が可能です。最初に簡単な例として、共通インデクスが割り当てられた Series 同士で足し算を実行してみます。

# PANDAS_SERIES_ADD

# In[1]

import numpy as np
import pandas as pd

# Seriesオブジェクトを生成
x = pd.Series([10, 20, 30], index=list("ABC"))
y = pd.Series([ 5, 10, 15], index=list("ABC"))

print(x + y)
# A    15
# B    30
# C    45
# dtype: int64

今度は x のインデクスを逆順に定義し直します。

# In[2]

# xのインデクス順序を変更
x = pd.Series([10, 20, 30], index=list("BCA"))

print(x)
# B    10
# C    20
# A    30
# dtype: int64

改めて x に y を加えてみます。

# In[3]

# Series x
# B    10
# C    20
# A    30
# dtype: int64

# Series y
# A     5
# B    10
# C    15
# dtype: int64

print(x + y)
# A    35
# B    20
# C    35
# dtype: int64

結果を見ると、同じ明示的インデクスをもつ要素同士で足し算されていることがわかります。また、x + y のインデクスは A から順に整列しています。このように、Seriesオブジェクトは自動ソート機能を備えています。
 
pandas はもっと複雑な演算にも対応しています。今度は互いに異なるインデクスを含む Series 同士の演算を試みます。x と y をあらためて次のように定義し直します。

# In[4]

# Seriesオブジェクトを生成
x = pd.Series([10, 20, 30], index=list("CBA"))
y = pd.Series([ 5, 10, 15], index=list("BDC"))

print(x,"\n")
print(y)

# C    10
# B    20
# A    30
# dtype: int64 

# B     5
# D    10
# C    15
# dtype: int64

x にはインデクス “D” の要素が含まれておらず、y にはインデクス “A” の要素が含まれていません。x と y を加えると次のような結果となります。

# In[5]

# xにyを加える
print(x + y)

# A     NaN
# B    25.0
# C    25.0
# D     NaN
# dtype: float64

インデクス “A” とインデクス “D” では、要求される演算が実行できないので「欠損値」として扱われ、NaN (Not a Number : 非数) で埋められています (欠損値については、こちらの記事で詳しく解説しています)。
[pandas] Series のインデクス整列01しかし状況によっては、欠損値に NaN 以外を与えたいこともあります。たとえば、add()メソッドの引数 fill_value に 0 を渡すと、x と y にそれぞれ仮想的なインデクス “D” とインデクス “A” を付加して、要素 0 を割り当てて足し算できます。
[pandas] Series のインデクス整列02 fill_values

# In[6]

# x に y を加える
# 仮想インデクス "A","D"に0を割り当てて演算を実行
z = x.add(y, fill_value=0)

print(z)
# A    30.0
# B    25.0
# C    25.0
# D    10.0
# dtype: float64

Seriesオブジェクトは、他にも以下のような算術メソッドを備えています。

演算の種類 算術メソッド
加算 add()
減算 sub()
乗算 mul()
除算 div()
切り捨て除算 floordiv()
剰余 mod()
べき乗 pow()

 

コメント

  1. あとりえこばと より:

    pandas.Seriesについて、ChatGPT に対話形式で解説してもらいました。

    生徒: 先生、pandasのSeriesについて教えてください。Seriesって何ですか?

    先生: もちろんです。pandasのSeriesは、1次元のデータ構造であり、1つの列を表現するために使用されます。

    生徒: なるほど、1次元のデータ構造で1つの列を表現するんですね。DataFrameとは違うんですか?

    先生: そうです、DataFrameとは異なります。DataFrameは複数の列と行からなるテーブル形式のデータを扱いますが、Seriesは単一の列のデータを扱います。

    生徒: なるほど、Seriesが1つの列のデータを表現するんですね。具体的な例を教えていただけますか?

    先生: もちろんです。例えば、以下のような名前のSeriesを考えましょう。
    ◆◆◆◆◆
    0  太郎
    1  花子
    2  健太
    ◆◆◆◆◆
    この場合、0、1、2がインデックスと呼ばれるラベルで付けられた値(名前)を表しています。

    生徒: インデックスというのは、行のラベルのことですか?

    先生: その通りです。Seriesは値の配列にインデックスを付けることで、個々の要素にラベルを持たせることができます。このラベルはデータに対して意味を持たせたり、特定の要素にアクセスする際に便利です。

    生徒: なるほど、ラベルを付けてデータを管理することができるんですね。Seriesではどのような操作ができるんですか?

    先生: Seriesでは、インデックスを使って要素の選択やフィルタリング、演算などが行えます。また、Seriesには組み込みのメソッドや関数を使ってデータの集計や統計処理も行うことができます。

    生徒: なるほど、インデックスを使って要素の操作や統計処理ができるんですね。

    先生: 正解です。Seriesは単一の列のデータを効果的に扱うためのデータ構造です。DataFrameと併用することで、より複雑なデータ操作や分析が可能になります。

    生徒: 分かりました!Seriesは列のデータを扱うための便利な構造なんですね。ありがとうございます!