pandas.DataFrame, SeriesとNumPy配列ndarrayを相互に変換
pandas.DataFrame
, pandas.Series
とNumPy配列numpy.ndarray
は相互に変換できる。
DataFrame
,Series
のvalues
属性でndarray
を取得- NumPy配列
ndarray
からDataFrame
,Series
を生成 - メモリの共有(ビューとコピー)の注意
- pandas
0.24.0
以降:to_numpy()
それぞれについてサンプルコードとともに説明する。
なお、pandas.DataFrame
, pandas.Series
にはas_matrix()
というnumpy.ndarray
を返すメソッドもあるが、バージョン0.23.0からdeprecated(非推奨)になっている。
pandas.DataFrame
, pandas.Series
とPython標準のリスト型list
を相互に変換する方法、pandas.DataFrame
とpandas.Series
を相互に変換する方法については以下の記事を参照。
pandas.DataFrame, Seriesのvalues属性でNumPy配列ndarrayを取得
pandas.DataFrame
, pandas.Series
いずれもvalues
属性でNumPy配列numpy.ndarray
を取得できる。なお、pandas0.24.0
以降は最後に紹介するto_numpy()
メソッドの使用が推奨されている。
- pandas.DataFrame.values — pandas 0.25.1 documentation
- pandas.Series.values — pandas 0.25.1 documentation
pandas.DataFrame
の場合。
import numpy as np
import pandas as pd
df = pd.DataFrame(data=[[1, 2, 3], [4, 5, 6]], columns=['a', 'b', 'c'])
print(df)
# a b c
# 0 1 2 3
# 1 4 5 6
a_df = df.values
print(a_df)
# [[1 2 3]
# [4 5 6]]
print(type(a_df))
# <class 'numpy.ndarray'>
print(a_df.dtype)
# int64
pandas.Series
の場合。
s = df['a']
print(s)
# 0 1
# 1 4
# Name: a, dtype: int64
a_s = s.values
print(a_s)
# [1 4]
print(type(a_s))
# <class 'numpy.ndarray'>
print(a_s.dtype)
# int64
取得できるndarray
のデータ型dtype
は元のpandas.DataFrame
, pandas.Series
のdtype
と同じ。
df_f = pd.DataFrame([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]])
print(df_f)
# 0 1 2
# 0 0.1 0.2 0.3
# 1 0.4 0.5 0.6
a_df_f = df_f.values
print(a_df_f)
# [[0.1 0.2 0.3]
# [0.4 0.5 0.6]]
print(type(a_df_f))
# <class 'numpy.ndarray'>
print(a_df_f.dtype)
# float64
数値と文字列が混在するpandas.DataFrame
はobject
型のndarray
となる。
df_multi = pd.read_csv('data/src/sample_pandas_normal.csv')
print(df_multi)
# name age state point
# 0 Alice 24 NY 64
# 1 Bob 42 CA 92
# 2 Charlie 18 CA 70
# 3 Dave 68 TX 70
# 4 Ellen 24 CA 88
# 5 Frank 30 NY 57
a_df_multi = df_multi.values
print(a_df_multi)
# [['Alice' 24 'NY' 64]
# ['Bob' 42 'CA' 92]
# ['Charlie' 18 'CA' 70]
# ['Dave' 68 'TX' 70]
# ['Ellen' 24 'CA' 88]
# ['Frank' 30 'NY' 57]]
print(type(a_df_multi))
# <class 'numpy.ndarray'>
print(a_df_multi.dtype)
# object
ndarray
のobject
型についての詳細は以下の記事を参照。
DataFrame
の特定の列だけndarray
に変換したい場合は、列を抽出したDataFrame
のvalues
を取得すればよい。列の抽出については以下の記事を参照。
数値の列だけ選択するとndarray
の型もobject
ではなくその型になる。
a_df_int = df_multi[['age', 'point']].values
print(a_df_int)
# [[24 64]
# [42 92]
# [18 70]
# [68 70]
# [24 88]
# [30 57]]
print(type(a_df_int))
# <class 'numpy.ndarray'>
print(a_df_int.dtype)
# int64
場合によっては.T
で転置したほうが使いやすいかもしれない。
print(a_df_int.T)
# [[24 42 18 68 24 30]
# [64 92 70 70 88 57]]
条件を指定して特定の型の列だけ抽出することもできる。例えばint64
型の列のみ抽出したい場合は以下のように書ける。
a_df_int = df_multi.select_dtypes(include=int).values
print(a_df_int)
# [[24 64]
# [42 92]
# [18 70]
# [68 70]
# [24 88]
# [30 57]]
print(type(a_df_int))
# <class 'numpy.ndarray'>
print(a_df_int.dtype)
# int64
select_dtypes()
を使ったデータ型dtype
による列の抽出についての詳細は以下の記事を参照。
そのほか、条件を満たす行名・列名の行・列のみを抽出することもできる。以下の記事を参照。
元のpandas.DataFrame
と変換したnumpy.ndarray
でメモリを共有している場合があり、いずれかの値を変更するともう一方の値も変更されることがある。後述。
NumPy配列ndarrayからpandas.DataFrame, Seriesを生成
NumPy配列numpy.ndarray
はpandas.DataFrame
およびpandas.Series
のコンストラクタの第一引数data
に指定できる。後述のように、numpy.ndarray
と生成したpandas.DataFrame
, pandas.Series
はメモリを共有する。
pandas.Seriesを生成
コンストラクタに他の引数を何も指定しないと、元のndarray
の型のSeries
となる。
import numpy as np
import pandas as pd
a = np.arange(4)
print(a)
# [0 1 2 3]
s = pd.Series(a)
print(s)
# 0 0
# 1 1
# 2 2
# 3 3
# dtype: int64
インデックス名index
やSeries
の名前name
、データ型dtype
などを引数で指定することもできる。
index = ['A', 'B', 'C', 'D']
name = 'sample'
s = pd.Series(data=a, index=index, name=name, dtype='float')
print(s)
# A 0.0
# B 1.0
# C 2.0
# D 3.0
# Name: sample, dtype: float64
pandasのdtype
については以下の記事を参照。
多次元のndarray
をSeries
のコンストラクタのdata
に指定するとエラーになる。
a = np.arange(12).reshape((4, 3))
print(a)
# [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]]
# s = pd.Series(a)
# print(s)
# Exception: Data must be 1-dimensional
例えば二次元のndarray
の行や列を選択してpandas.Series
に変換することは可能。
s = pd.Series(a[2])
print(s)
# 0 6
# 1 7
# 2 8
# dtype: int64
s = pd.Series(a.T[2])
print(s)
# 0 2
# 1 5
# 2 8
# 3 11
# dtype: int64
pandas.DataFrameを生成
Series
と同じく、コンストラクタに他の引数を何も指定しないと、元のndarray
の型のDataFrame
となる。
a = np.arange(12).reshape((4, 3))
print(a)
# [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]]
df = pd.DataFrame(a)
print(df)
# 0 1 2
# 0 0 1 2
# 1 3 4 5
# 2 6 7 8
# 3 9 10 11
行名index
や列の名columns
、データ型dtype
などを引数で指定することもできる。
index = ['A', 'B', 'C', 'D']
columns = ['a', 'b', 'c']
df = pd.DataFrame(data=a, index=index, columns=columns, dtype='float')
print(df)
# a b c
# A 0.0 1.0 2.0
# B 3.0 4.0 5.0
# C 6.0 7.0 8.0
# D 9.0 10.0 11.0
メモリの共有(ビューとコピー)の注意
values
属性やコンストラクタで相互に変換したpandas.DataFrame
やpandas.Series
とnumpy.ndarray
は互いにメモリを共有している場合がある。メモリが共有されている(片方がもう一方のビューである)と、一方の値を変更するともう一方の値も変更される。それぞれを別々に処理・利用したい場合は要注意。
以下のサンプルコードとその結果はpandas0.25.1
でのもの。バージョンが違うと挙動が異なる場合がある。
values属性
まずは以下のような場合。
df = pd.DataFrame(data=[[1, 2, 3], [4, 5, 6]], columns=['a', 'b', 'c'])
print(df)
# a b c
# 0 1 2 3
# 1 4 5 6
a_values = df.values
print(a_values)
# [[1 2 3]
# [4 5 6]]
values
はビューを返し、一方の値を変更するともう一方の値も変更される。np.shares_memory()
で判定できる。
print(np.shares_memory(a_values, df))
# True
a_values[0, 0] = 100
print(a_values)
# [[100 2 3]
# [ 4 5 6]]
print(df)
# a b c
# 0 100 2 3
# 1 4 5 6
常にビューを返すわけではなく、例えば各列のデータ型dtype
が異なる場合はコピー。
df_if = pd.DataFrame(data=[[1, 0.1], [2, 0.2]], columns=['int', 'float'])
print(df_if)
# int float
# 0 1 0.1
# 1 2 0.2
print(df_if.dtypes)
# int int64
# float float64
# dtype: object
a_values_if = df_if.values
print(a_values_if)
# [[1. 0.1]
# [2. 0.2]]
print(np.shares_memory(a_values_if, df_if))
# False
a_values_if[0, 0] = 100
print(a_values_if)
# [[100. 0.1]
# [ 2. 0.2]]
print(df_if)
# int float
# 0 1 0.1
# 1 2 0.2
そのほか、行や列などの範囲を指定してvalues
を取得する場合は指定方法によってビューかコピーかが異なったりする。
print(df[['a', 'c']].values)
# [[100 3]
# [ 4 6]]
print(np.shares_memory(df[['a', 'c']].values, df))
# False
print(df.iloc[:, ::2].values)
# [[100 3]
# [ 4 6]]
print(np.shares_memory(df.iloc[:, ::2].values, df))
# True
ビューだと問題がある場合はvalues
のcopy()
で明示的にコピーを生成すればよい。
a_values_copy = df.values.copy()
print(a_values_copy)
# [[100 2 3]
# [ 4 5 6]]
print(np.shares_memory(a_values_copy, df))
# False
a_values_copy[0, 0] = 10
print(a_values_copy)
# [[10 2 3]
# [ 4 5 6]]
print(df)
# a b c
# 0 100 2 3
# 1 4 5 6
pandas.DataFrame, pandas.Seriesのコンストラクタ
コンストラクタpandas.DataFrame()
, pandas.Series()
にnumpy.ndarray
を渡すとメモリが共有される。一方の値を変更するともう一方の値も変更される。
a = np.array([[1, 2, 3], [4, 5, 6]])
print(a)
# [[1 2 3]
# [4 5 6]]
df_a = pd.DataFrame(a, columns=['a', 'b', 'c'])
print(df_a)
# a b c
# 0 1 2 3
# 1 4 5 6
print(np.shares_memory(a, df_a))
# True
a[0, 0] = 100
print(a)
# [[100 2 3]
# [ 4 5 6]]
print(df_a)
# a b c
# 0 100 2 3
# 1 4 5 6
df_a.iat[1, 0] = 10
print(df_a)
# a b c
# 0 100 2 3
# 1 10 5 6
print(a)
# [[100 2 3]
# [ 10 5 6]]
メモリを共有させたくない場合はnumpy.ndarray
のcopy()
でコピーをコンストラクタの引数に指定する。
df_a_copy = pd.DataFrame(a.copy(), columns=['a', 'b', 'c'])
print(df_a_copy)
# a b c
# 0 100 2 3
# 1 10 5 6
a[0, 0] = 1
print(a)
# [[ 1 2 3]
# [10 5 6]]
print(df_a_copy)
# a b c
# 0 100 2 3
# 1 10 5 6
pandas0.24.0以降: to_numpy()
pandas0.24.0
でpandas.DataFrame
, pandas.Series
にto_numpy()
メソッドが追加された。上述のvalues
属性と同様、numpy.ndarray
を返す。
公式ドキュメントではvalues
属性ではなくto_numpy()
メソッドの使用が推奨されているが、バージョン0.25.1
時点ではvalues
属性を使っても警告などは出ない。
- pandas.DataFrame.to_numpy — pandas 0.25.1 documentation
- pandas.Series.to_numpy — pandas 0.25.1 documentation
df = pd.DataFrame(data=[[1, 2, 3], [4, 5, 6]], columns=['a', 'b', 'c'])
print(df)
# a b c
# 0 1 2 3
# 1 4 5 6
a = df.to_numpy()
print(a)
# [[1 2 3]
# [4 5 6]]
print(type(a))
# <class 'numpy.ndarray'>
デフォルトではvalues
属性と同様、ビュー(メモリを共有するnumpy.ndarray
)を返す場合がある。
print(np.shares_memory(df, a))
# True
a[0, 0] = 100
print(a)
# [[100 2 3]
# [ 4 5 6]]
print(df)
# a b c
# 0 100 2 3
# 1 4 5 6
引数copy
をTrue
とするとコピーが返される。デフォルトはcopy=False
。
a_copy = df.to_numpy(copy=True)
print(a_copy)
# [[100 2 3]
# [ 4 5 6]]
print(np.shares_memory(df, a_copy))
# False
a_copy[0, 0] = 10
print(a_copy)
# [[10 2 3]
# [ 4 5 6]]
print(df)
# a b c
# 0 100 2 3
# 1 4 5 6
デフォルト(copy=False
)でもビューではなくコピーが返される場合もある。copy=True
は必ずコピーを返すが、copy=False
は必ずビューを返すとは限らない。
上述のvalues
属性がコピーを返すような場合はデフォルト(copy=False
)でもコピーとなる。
a_cols = df[['a', 'c']].to_numpy()
print(a_cols)
# [[100 3]
# [ 4 6]]
print(np.shares_memory(df, a_cols))
# False
引数dtype
でデータ型を指定可能。データ型が変更された場合もコピーを返す。
a_f = df.to_numpy(dtype=float)
print(a_f)
# [[100. 2. 3.]
# [ 4. 5. 6.]]
print(np.shares_memory(df, a_f))
# False