pandas.DataFrame, SeriesとPythonのリストを相互に変換

Modified: | Tags: Python, pandas, リスト

pandasのDataFrame, SeriesとPython組み込みのリストlistを相互に変換する方法を説明する。

なお、便宜上「変換」という言葉を使っているが、実際は元のオブジェクトはそのままで新たな型のオブジェクトが生成される。

DataFrame, SeriesとNumPy配列ndarrayの相互変換、DataFrameSeriesの相互変換については以下の記事を参照。

本記事のサンプルコードのpandasのバージョンは以下の通り。バージョンによって仕様が異なる可能性があるので注意。

import pandas as pd

print(pd.__version__)
# 2.1.4

リストをpandasのDataFrame, Seriesに変換

pd.DataFrame(), pd.Series()でリストをDataFrame, Seriesに変換

コンストラクタpd.Series(), pd.DataFrame()の第一引数にリストを指定すると、そのリストを元にSeries, DataFrameが生成される。

l_1d = [0, 10, 20]

print(pd.Series(l_1d))
# 0     0
# 1    10
# 2    20
# dtype: int64

l_2d = [[0, 10, 20], [30, 40, 50]]

print(pd.DataFrame(l_2d))
#     0   1   2
# 0   0  10  20
# 1  30  40  50

pd.DataFrame()に一次元リストをそのまま指定すると一列のDataFrame[一次元リスト]として指定すると一行のDataFrameが生成される。

print(pd.DataFrame(l_1d))
#     0
# 0   0
# 1  10
# 2  20

print(pd.DataFrame([l_1d]))
#    0   1   2
# 0  0  10  20

二次元リストの行・列を入れ替えたい場合は、転置して指定する。

print(pd.DataFrame(zip(*l_2d)))
#     0   1
# 0   0  30
# 1  10  40
# 2  20  50

行名・列名の指定: 引数index, columns

引数indexで行名(行ラベル)、引数columnsで列名(列ラベル)を指定できる。

print(pd.Series(l_1d, index=['X', 'Y', 'Z']))
# X     0
# Y    10
# Z    20
# dtype: int64

print(pd.DataFrame(l_2d, index=['X', 'Y'], columns=['A', 'B', 'C']))
#     A   B   C
# X   0  10  20
# Y  30  40  50

Series, DataFrameを生成したあとで行名・列名を設定・変更することも可能。

データ型の指定: 引数dtype

DataFrameの各列およびSeriesのデータ型dtypeは、リストの値から自動的に決まる。

例えば、整数intと浮動小数点数floatが混在する列のデータ型はfloat、数値と文字列が混在する列のデータ型はobjectとなる。

l_2d_multi = [[0, 0.0, 'abc', 123, 'abc'], [10, 0.1, 'xyz', 1.23, 100]]

print(pd.DataFrame(l_2d_multi))
#     0    1    2       3    4
# 0   0  0.0  abc  123.00  abc
# 1  10  0.1  xyz    1.23  100

print(pd.DataFrame(l_2d_multi).dtypes)
# 0      int64
# 1    float64
# 2     object
# 3    float64
# 4     object
# dtype: object

pd.DataFrame(), pd.Series()の引数dtypeでデータ型を指定して生成することもできる。

print(pd.DataFrame(l_2d, dtype=float))
#       0     1     2
# 0   0.0  10.0  20.0
# 1  30.0  40.0  50.0

pandasのデータ型についての詳細は以下の記事を参照。

ラベル(行名・列名)を含むリストの場合

ラベルと値のペアのリストからSeriesを生成するには、ラベルと値に分解してpd.Series()に渡す。

l_1d_index = [['X', 0], ['Y', 1], ['Z', 2]]

index, values = zip(*l_1d_index)
print(index)
# ('X', 'Y', 'Z')

print(values)
# (0, 1, 2)

print(pd.Series(values, index=index))
# X    0
# Y    1
# Z    2
# dtype: int64

ラベルと複数の値からなるリストからDataFrameを生成するには、全体を読み込んでからset_index()メソッドでindexを指定する。

l_2d_index = [['X', 0, 0.0], ['Y', 1, 0.1], ['Z', 2, 0.2]]

df_index = pd.DataFrame(l_2d_index, columns=['idx', 'A', 'B'])
print(df_index)
#   idx  A    B
# 0   X  0  0.0
# 1   Y  1  0.1
# 2   Z  2  0.2

print(df_index.set_index('idx'))
#      A    B
# idx        
# X    0  0.0
# Y    1  0.1
# Z    2  0.2

元のリストに列名も含まれている場合、最初の行を引数columns、二行目以降を第一引数に指定する。二行目以降はスライスで取得可能。

l_2d_index_columns = [['idx', 'A', 'B'], ['X', 0, 0.0], ['Y', 1, 0.1], ['Z', 2, 0.2]]

df_index_columns = pd.DataFrame(l_2d_index_columns[1:], columns=l_2d_index_columns[0])
print(df_index_columns)
#   idx  A    B
# 0   X  0  0.0
# 1   Y  1  0.1
# 2   Z  2  0.2

print(df_index_columns.set_index('idx'))
#      A    B
# idx        
# X    0  0.0
# Y    1  0.1
# Z    2  0.2

pandasのDataFrame, Seriesをリストに変換

Seriesのtolist(), to_list()メソッドでリストに変換

Seriestolist()またはto_list()メソッドでデータ列をリストに変換できる。

s = pd.Series([0, 10, 20])
print(s)
# 0     0
# 1    10
# 2    20
# dtype: int64

print(s.tolist())
# [0, 10, 20]

print(s.to_list())
# [0, 10, 20]

DataFrameのvalues属性とndarrayのtolist()メソッドでリストに変換

pandas 2.1.4時点でDataFrameにはtolist()to_list()メソッドはない。values属性でNumPy配列ndarrayに変換し、ndarraytolist()メソッドでリストに変換する。

df = pd.DataFrame([[0, 10, 20], [30, 40, 50]])
print(df)
#     0   1   2
# 0   0  10  20
# 1  30  40  50

print(df.values.tolist())
# [[0, 10, 20], [30, 40, 50]]

index, columnsを含めてリストに変換

行名indexもリストのデータとして残すには、reset_index()メソッドでindexをリセットしてデータ列にする。

s_index = pd.Series([0, 1, 2], index=['X', 'Y', 'Z'])
print(s_index)
# X    0
# Y    1
# Z    2
# dtype: int64

print(s_index.reset_index())
#   index  0
# 0     X  0
# 1     Y  1
# 2     Z  2

print(s_index.reset_index().values.tolist())
# [['X', 0], ['Y', 1], ['Z', 2]]
df_index = pd.DataFrame([[0, 1, 2], [3, 4, 5]], index=['A', 'B'], columns=['X', 'Y', 'Z'])
print(df_index)
#    X  Y  Z
# A  0  1  2
# B  3  4  5

print(df_index.reset_index())
#   index  X  Y  Z
# 0     A  0  1  2
# 1     B  3  4  5

print(df_index.reset_index().values.tolist())
# [['A', 0, 1, 2], ['B', 3, 4, 5]]

pandas 2.1.4時点で列名columnsをリセットするメソッドはない。DataFrameで行名も列名もリストのデータとして残すには、reset_index()を適用したあと.Tで転置して再度reset_index()を適用し、さらに.Tで元に戻す。もっといい方法があるかもしれない。

print(df_index.reset_index().T.reset_index().T.values.tolist())
# [['index', 'X', 'Y', 'Z'], ['A', 0, 1, 2], ['B', 3, 4, 5]]

index, columnsをリストに変換

Seriesindex属性、および、DataFrameindex, columns属性はいずれもIndex型。tolist()またはto_list()メソッドでリストに変換できる。

s_index = pd.Series([0, 1, 2], index=['X', 'Y', 'Z'])
print(s_index)
# X    0
# Y    1
# Z    2
# dtype: int64

print(s_index.index)
# Index(['X', 'Y', 'Z'], dtype='object')

print(s_index.index.tolist())
# ['X', 'Y', 'Z']
df_index = pd.DataFrame([[0, 1, 2], [3, 4, 5]], index=['A', 'B'], columns=['X', 'Y', 'Z'])
print(df_index)
#    X  Y  Z
# A  0  1  2
# B  3  4  5

print(df_index.index)
# Index(['A', 'B'], dtype='object')

print(df_index.index.tolist())
# ['A', 'B']

print(df_index.columns)
# Index(['X', 'Y', 'Z'], dtype='object')

print(df_index.columns.tolist())
# ['X', 'Y', 'Z']

なお、Index型はそのままfor文で要素を取り出したり、[]で位置を指定して要素を取得したりできる。スライスも使えるが、要素の変更はできない。要素を取得するだけならリストに変換する必要はない。

for i in df_index.columns:
    print(i, type(i))
# X <class 'str'>
# Y <class 'str'>
# Z <class 'str'>

print(df_index.columns[0])
# X

print(df_index.columns[:2])
# Index(['X', 'Y'], dtype='object')

# df_index.columns[0] = 'x'
# TypeError: Index does not support mutable operations

関連カテゴリー

関連記事