pandas.Seriesのインデックスと値を入れ替え(スワップ)

Posted: | Tags: Python, pandas

pandas.Seriesのインデックス(ラベル)と値を入れ替える(スワップする)方法を説明する。

以下のpandas.Seriesを例とする。timeitモジュールは処理速度計測のためにインポートしている。

import pandas as pd
import timeit

s = pd.Series(['a', 'b', 'c', 'd', 'e'])

print(s)
# 0    a
# 1    b
# 2    c
# 3    d
# 4    e
# dtype: object

以下の内容について説明する。

  • コンストラクタにインデックスと値を入れ替えて指定
  • values属性を使う場合と使わない場合の速度比較

コンストラクタにインデックスと値を入れ替えて指定

pandas.Seriesにインデックスと値を入れ替えるメソッドはないので、コンストラクタpandas.Series()の第一引数dataと第二引数indexにそれぞれ元のpandas.Seriesのインデックスと値を指定して新たなpandas.Seriesを生成する。

s_swap = pd.Series(s.index.values, s.values)

print(s_swap)
# a    0
# b    1
# c    2
# d    3
# e    4
# dtype: int64

ここではpandas.Seriesおよびそのindexvalues属性(NumPy配列numpy.ndarray)を使っている。

print(s.values)
# ['a' 'b' 'c' 'd' 'e']

print(type(s.values))
# <class 'numpy.ndarray'>

print(s.index.values)
# [0 1 2 3 4]

print(type(s.index.values))
# <class 'numpy.ndarray'>

values属性を使わずにそのまま指定しても同じ結果が得られるが、values属性を使ったほうが多少速い(後述)。

s_swap = pd.Series(s.index, s)

print(s_swap)
# a    0
# b    1
# c    2
# d    3
# e    4
# dtype: int64

values属性を使う場合と使わない場合の速度比較

values属性を使う場合と使わない場合の速度をtimeitモジュールを使って比較する。

以下のようにvalues属性を使ったほうが速い。

loop = 10000

result = timeit.timeit(lambda: pd.Series(s.index.values, s.values), number=loop)
print(result / loop)
# 8.694580160081386e-05

result = timeit.timeit(lambda: pd.Series(s.index, s), number=loop)
print(result / loop)
# 0.00010916587258689105

元のpandas.Seriesのサイズが大きくても同じ。

s_large = pd.concat([s] * 100000)

print(len(s_large))
# 500000

loop = 100

result = timeit.timeit(lambda: pd.Series(s_large.index.values, s_large.values), number=loop)
print(result / loop)
# 0.005923357829451561

result = timeit.timeit(lambda: pd.Series(s_large.index, s_large), number=loop)
print(result / loop)
# 0.006492725329007953

とはいえ、よっぽど巨大なpandas.Seriesでない限りそんなに時間がかかるわけでもないので、values属性を使っても使わなくてもどっちでもいいかもしれない。

関連カテゴリー

関連記事