pandas データフレームを NumPy 配列に変換するにはどうすればよいですか?
データフレーム:
import numpy as np
import pandas as pd
index = [1, 2, 3, 4, 5, 6, 7]
a = [np.nan, np.nan, np.nan, 0.1, 0.1, 0.1, 0.1]
b = [0.2, np.nan, 0.2, 0.2, 0.2, np.nan, np.nan]
c = [np.nan, 0.5, 0.5, np.nan, 0.5, 0.5, np.nan]
df = pd.DataFrame({'A': a, 'B': b, 'C': c}, index=index)
df = df.rename_axis('ID')
与える
A B C
ID
1 NaN 0.2 NaN
2 NaN NaN 0.5
3 NaN 0.2 0.5
4 0.1 0.2 NaN
5 0.1 0.2 0.5
6 0.1 NaN 0.5
7 0.1 NaN NaN
これを次のように NumPy 配列に変換したいと思います。
array([[ nan, 0.2, nan],
[ nan, nan, 0.5],
[ nan, 0.2, 0.5],
[ 0.1, 0.2, nan],
[ 0.1, 0.2, 0.5],
[ 0.1, nan, 0.5],
[ 0.1, nan, nan]])
また、このように dtype を保存することは可能ですか?
array([[ 1, nan, 0.2, nan],
[ 2, nan, nan, 0.5],
[ 3, nan, 0.2, 0.5],
[ 4, 0.1, 0.2, nan],
[ 5, 0.1, 0.2, 0.5],
[ 6, 0.1, nan, 0.5],
[ 7, 0.1, nan, nan]],
dtype=[('ID', '<i4'), ('A', '<f8'), ('B', '<f8'), ('B', '<f8')])
ベストアンサー1
使用df.to_numpy()
よりも優れているdf.values
理由は次のとおりです。*
values
およびの使用を廃止する時期が来ましたas_matrix()
。
pandas v0.24.0 では、pandas オブジェクトから NumPy 配列を取得するための 2 つの新しいメソッドが導入されました。
to_numpy()
Index
は、、、Series
およびDataFrame
オブジェクト上で定義され、array
は、Index
およびSeries
オブジェクトでのみ定義されます。
v0.24のドキュメントにアクセスすると.values
次のような大きな赤い警告が表示されます:
警告:
DataFrame.to_numpy()
代わりに を使用することをお勧めします。
見るv0.24.0リリースノートのこのセクション、 そしてこの答え詳細については。
* - はto_numpy()
、将来にわたって多くのバージョンで確実に実行する必要がある製品コードに推奨される方法です。ただし、jupyter またはターミナルでスクラッチパッドを作成するだけの場合は、.values
入力時間を数ミリ秒節約するために を使用することは許容される例外です。いつでも、後から fit n finish を追加できます。
一貫性の向上に向けて:to_numpy()
API 全体の一貫性を高めるために、to_numpy
DataFrames から基礎となる NumPy 配列を抽出する新しいメソッドが導入されました。
# Setup
df = pd.DataFrame(data={'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]},
index=['a', 'b', 'c'])
# Convert the entire DataFrame
df.to_numpy()
# array([[1, 4, 7],
# [2, 5, 8],
# [3, 6, 9]])
# Convert specific columns
df[['A', 'C']].to_numpy()
# array([[1, 7],
# [2, 8],
# [3, 9]])
上で述べたように、このメソッドはオブジェクトIndex
およびSeries
オブジェクトでも定義されています(ここ)。
df.index.to_numpy()
# array(['a', 'b', 'c'], dtype=object)
df['A'].to_numpy()
# array([1, 2, 3])
デフォルトではビューが返されるため、変更を加えると元のビューに影響します。
v = df.to_numpy()
v[0, 0] = -1
df
A B C
a -1 4 7
b 2 5 8
c 3 6 9
代わりにコピーが必要な場合は、 を使用してくださいto_numpy(copy=True)
。
ExtensionTypes の pandas >= 1.0 アップデート
pandas 1.x を使用している場合は、拡張タイプをより多く扱うことになるでしょう。これらの拡張タイプが正しく変換されるように、もう少し注意する必要があります。
a = pd.array([1, 2, None], dtype="Int64")
a
<IntegerArray>
[1, 2, <NA>]
Length: 3, dtype: Int64
# Wrong
a.to_numpy()
# array([1, 2, <NA>], dtype=object) # yuck, objects
# Correct
a.to_numpy(dtype='float', na_value=np.nan)
# array([ 1., 2., nan])
# Also correct
a.to_numpy(dtype='int', na_value=-1)
# array([ 1, 2, -1])
これはドキュメントで言及されている。
dtypes
結果にが必要な場合...
別の回答に示されているように、DataFrame.to_records
これはこれを行う良い方法です。
df.to_records()
# rec.array([('a', 1, 4, 7), ('b', 2, 5, 8), ('c', 3, 6, 9)],
# dtype=[('index', 'O'), ('A', '<i8'), ('B', '<i8'), ('C', '<i8')])
残念ながら、これは では実行できませんto_numpy
。ただし、代わりに を使用できますnp.rec.fromrecords
。
v = df.reset_index()
np.rec.fromrecords(v, names=v.columns.tolist())
# rec.array([('a', 1, 4, 7), ('b', 2, 5, 8), ('c', 3, 6, 9)],
# dtype=[('index', '<U1'), ('A', '<i8'), ('B', '<i8'), ('C', '<i8')])
パフォーマンス的には、ほぼ同じです (実際、 を使用するとrec.fromrecords
少し速くなります)。
df2 = pd.concat([df] * 10000)
%timeit df2.to_records()
%%timeit
v = df2.reset_index()
np.rec.fromrecords(v, names=v.columns.tolist())
12.9 ms ± 511 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
9.56 ms ± 291 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
新しいメソッドを追加する理由
to_numpy()
(に加えてarray
)は、2つのGitHubの問題での議論の結果として追加されました。GH19954そしてGH23623。
具体的には、ドキュメント根拠を述べます:
[ ...] の場合、
.values
返される値が実際の配列なのか、その変換なのか、あるいは pandas のカスタム配列 ( など) の 1 つなのかは不明でしたCategorical
。たとえば、 の場合PeriodIndex
、は毎回、期間オブジェクトの.values
新しい を生成します。 [...]ndarray
to_numpy
API の一貫性を向上させることを目指しており、これは正しい方向への大きな一歩です。.values
現在のバージョンでは廃止されませんが、将来的には廃止される可能性があると予想されるため、ユーザーにはできるだけ早く新しい API に移行することを強くお勧めします。
他の解決策に対する批判
DataFrame.values
すでに述べたように、動作に一貫性がありません。
DataFrame.get_values()
だったv1.0でひっそりと削除されましたは v0.25 で非推奨になりました。それ以前は、 の単なるラッパーだったのでDataFrame.values
、上記の内容がすべて適用されます。
DataFrame.as_matrix()
v1.0 で削除され、v0.23 では非推奨になりました。使用しないでください。