note.nkmk.me

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

Date: 2018-03-29 / Modified: 2019-09-03 / tags: Python, pandas, リスト

pandas.DataFrame, pandas.SeriesとPython標準のリスト型listは相互に変換できる。

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

  • リスト型listpandas.DataFrame, pandas.Seriesに変換
    • データのみのリストの場合
    • データとラベル(行名・列名)を含むリストの場合
  • pandas.DataFrame, pandas.Seriesをリスト型listに変換
    • データ部分をリスト型listに変換
    • データ部分とラベル(行名・列名)をリスト型listに変換
    • ラベル(行名・列名)をリスト型listに変換

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

スポンサーリンク

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

データのみのリストの場合

それぞれのコンストラクタpandas.DataFrame(), pandas.Series()の第一引数にリスト型のオブジェクトを渡すと、リストを元にpandas.DataFrame, pandas.Seriesが生成される。

一次元のリストからpandas.Seriesを生成する例。引数indexでラベルを指定することもできる。

import pandas as pd

l_1d = [0, 1, 2]

s = pd.Series(l_1d)
print(s)
# 0    0
# 1    1
# 2    2
# dtype: int64

s = pd.Series(l_1d, index=['row1', 'row2', 'row3'])
print(s)
# row1    0
# row2    1
# row3    2
# dtype: int64

二次元配列(リストのリスト)からpandas.DataFrameを生成する例。引数indexで行名(行ラベル)、引数columnsで列名(列ラベル)を指定することもできる。

l_2d = [[0, 1, 2], [3, 4, 5]]

df = pd.DataFrame(l_2d)
print(df)
#    0  1  2
# 0  0  1  2
# 1  3  4  5

df = pd.DataFrame(l_2d,
                  index=['row1', 'row2'],
                  columns=['col1', 'col2', 'col3'])
print(df)
#       col1  col2  col3
# row1     0     1     2
# row2     3     4     5

pandas.DataFrame, pandas.Seriesを生成したあとでindex, columns属性を更新して行名・列名を設定・変更することも可能。

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

ラベルと値がペアとなったリストからpandas.Seriesを生成する場合。

ラベルの配列と値の配列に分解し、それをpandas.Series()の引数に渡す。*zip()を使った処理の詳細は以下の記事を参照。

l_1d_index = [['Alice', 0], ['Bob', 1], ['Charlie', 2]]

index, value = zip(*l_1d_index)
print(index)
# ('Alice', 'Bob', 'Charlie')

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

s_index = pd.Series(value, index=index)
print(s_index)
# Alice      0
# Bob        1
# Charlie    2
# dtype: int64

同様に、ラベルと複数の値からなるリストからpandas.DataFrameを生成する場合。

上述のpandas.Seriesのように配列を分解してもいいが、全体を読み込んでからset_index()メソッドでindex列を指定したほうが簡単。

l_2d_index = [['Alice', 0, 0.0], ['Bob', 1, 0.1], ['Charlie', 2, 0.2]]

df_index = pd.DataFrame(l_2d_index, columns=['name', 'val1', 'val2'])
print(df_index)
#       name  val1  val2
# 0    Alice     0   0.0
# 1      Bob     1   0.1
# 2  Charlie     2   0.2

df_index_set = df_index.set_index('name')
print(df_index_set)
#          val1  val2
# name               
# Alice       0   0.0
# Bob         1   0.1
# Charlie     2   0.2

なお、この例のように列ごとにデータ型dtypeが異なる場合もそれぞれの列に最適なデータ型dtypeが自動で選ばれる。

print(df_index_set.dtypes)
# val1      int64
# val2    float64
# dtype: object

元のリストに列名も含まれている場合。

最初の行をcolumnsに、2行目以降を第一引数にそれぞれ指定する。

l_2d_index_columns = [['name', 'val1', 'val2'], ['Alice', 0, 0.0], ['Bob', 1, 0.1], ['Charlie', 2, 0.2]]

df_index_columns = pd.DataFrame(l_2d_index_columns[1:], columns=l_2d_index_columns[0])
print(df_index_columns)
#       name  val1  val2
# 0    Alice     0   0.0
# 1      Bob     1   0.1
# 2  Charlie     2   0.2

df_index_columns_set = df_index_columns.set_index('name')
print(df_index_columns_set)
#          val1  val2
# name               
# Alice       0   0.0
# Bob         1   0.1
# Charlie     2   0.2

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

データ部分をリストに変換

pandas.DataFrame, pandas.Seriesをリスト型に直接変換するメソッドは無いため、values属性で取得できるNumPy配列ndarrayを経由して、ndarraytolist()メソッドでリストに変換する。

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

l_1d = s.values.tolist()
print(l_1d)
# [0, 1, 2]
df = pd.DataFrame([[0, 1, 2], [3, 4, 5]])
print(df)
#    0  1  2
# 0  0  1  2
# 1  3  4  5

l_2d = df.values.tolist()
print(l_2d)
# [[0, 1, 2], [3, 4, 5]]

values属性ではラベル(行名、列名)があっても無視される。

s_index = pd.Series([0, 1, 2], index=['row1', 'row2', 'row3'])
print(s_index)
# row1    0
# row2    1
# row3    2
# dtype: int64

l_1d = s_index.values.tolist()
print(l_1d)
# [0, 1, 2]
df_index = pd.DataFrame([[0, 1, 2], [3, 4, 5]],
                        index=['row1', 'row2'],
                        columns=['col1', 'col2', 'col3'])
print(df_index)
#       col1  col2  col3
# row1     0     1     2
# row2     3     4     5

l_2d = df_index.values.tolist()
print(l_2d)
# [[0, 1, 2], [3, 4, 5]]

データ部分とラベル(行名・列名)をリストに変換

ラベルもリストのデータとして残したい場合は、reset_index()メソッドでindex列をリセットしてデータ列にする。

l_1d_index = s_index.reset_index().values.tolist()
print(l_1d_index)
# [['row1', 0], ['row2', 1], ['row3', 2]]

列名(列ラベル)をリセットするメソッドは無いため、pandas.DataFrameで行名も列名もリストのデータとして残したい場合は、reset_index()メソッドを適用したあと.Tで転置して再度reset_index()メソッドを適用し、さらに.Tで元に戻す。

l_2d_index = df_index.reset_index().values.tolist()
print(l_2d_index)
# [['row1', 0, 1, 2], ['row2', 3, 4, 5]]

l_2d_index_columns = df_index.reset_index().T.reset_index().T.values.tolist()
print(l_2d_index_columns)
# [['index', 'col1', 'col2', 'col3'], ['row1', 0, 1, 2], ['row2', 3, 4, 5]]

ラベル(行名・列名)をリストに変換

ラベルのみをリストに変換したい場合、pandas.Seriesの場合はindex属性を利用する。index属性はIndex型(デフォルトの連番の場合はRangeIndex型)で、tolist()メソッドが用意されている。

print(s_index)
# row1    0
# row2    1
# row3    2
# dtype: int64

print(s_index.index)
# Index(['row1', 'row2', 'row3'], dtype='object')

print(type(s_index.index))
# <class 'pandas.core.indexes.base.Index'>

print(s_index.index.tolist())
# ['row1', 'row2', 'row3']

print(type(s_index.index.tolist()))
# <class 'list'>

pandas.DataFrameの場合も同様に、行ラベル(行名)はindex属性、列ラベル(列名)はcolumns属性を利用する。どちらもIndex型。

print(df_index)
#       col1  col2  col3
# row1     0     1     2
# row2     3     4     5

print(df_index.index)
# Index(['row1', 'row2'], dtype='object')

print(df_index.index.tolist())
# ['row1', 'row2']

print(df_index.columns)
# Index(['col1', 'col2', 'col3'], dtype='object')

print(df_index.columns.tolist())
# ['col1', 'col2', 'col3']

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

for i in s_index.index:
    print(i, type(i))
# row1 <class 'str'>
# row2 <class 'str'>
# row3 <class 'str'>

print(s_index.index[0])
# row1

print(s_index.index[:2])
# Index(['row1', 'row2'], dtype='object')

# s_index.index[0] = 'ROW1'
# TypeError: Index does not support mutable operations

inndexcolumnsの要素(行名・列名)を変更したい場合はrename()を使う。

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事