データフレームを作成する正しい方法™
TLDR; (太字のテキストを読むだけです)
ここでのほとんどの答えは、空のDataFrameを作成してそれを埋める方法を教えてくれますが、それが悪いことであると誰も教えてくれません。
これが私のアドバイスです:作業に必要なすべてのデータが揃うまで待ちます。リストを使用してデータを収集し、準備ができたらDataFrameを初期化します。
data = []
for a, b, c in some_function_that_yields_data():
data.append([a, b, c])
df = pd.DataFrame(data, columns=['A', 'B', 'C'])
リストに追加してDataFrameを一度に作成する方が、空のDataFrame(またはNaNの1つ)を作成して何度も追加するよりも常に安上がりです。また、リストはメモリ使用量が少なく、(必要な場合)の操作、追加、削除を行うためのデータ構造がはるかに軽量です。
この方法のもう1つの利点はdtypes
、自動的に推測されることです(object
すべてに割り当てるのではなく)。
最後の利点は、RangeIndex
がデータ用に自動的に作成されるため、心配する必要が1つ少なくappend
なりloc
ます(以下の貧しい人々とメソッドを見てください。インデックスを適切に処理する必要がある両方の要素が表示されます)。
してはいけないこと
append
またはconcat
ループ内
ここに私が初心者から見た最大の間違いがあります:
df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
df = df.append({'A': i, 'B': b, 'C': c}, ignore_index=True) # yuck
# or similarly,
# df = pd.concat([df, pd.Series({'A': i, 'B': b, 'C': c})], ignore_index=True)
メモリーはappend
、concat
操作ごとに再割り当てされます。これをループと組み合わせると、2次の複雑さの演算ができます。df.append
ドキュメントページから:
DataFrameに繰り返し行を追加すると、単一の連結よりも計算負荷が高くなる可能性があります。より良い解決策は、それらの行をリストに追加し、リストを元のDataFrameと一度に連結することです。
関連するもう1つの間違いdf.append
は、ユーザーが追記を忘れがちなのがインプレース関数ではないため、結果を割り当て直す必要があることです。また、dtypeについても考慮する必要があります。
df = pd.DataFrame(columns=['A', 'B', 'C'])
df = df.append({'A': 1, 'B': 12.3, 'C': 'xyz'}, ignore_index=True)
df.dtypes
A object # yuck!
B float64
C object
dtype: object
オブジェクト列を処理することは、パンダがそれらの列に対する操作をベクトル化できないため、決して良いことではありません。あなたはそれを修正するためにこれを行う必要があります:
df.infer_objects().dtypes
A int64
B float64
C object
dtype: object
loc
ループ内
loc
空で作成されたDataFrameに追加するために使用されることも確認しました。
df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
df.loc[len(df)] = [a, b, c]
以前と同様に、毎回必要なメモリ量を事前に割り当てていないため、新しい行を作成するたびにメモリが再成長します。それは同じくらい悪いですappend
、さらに醜いです。
NaNの空のDataFrame
次に、NaNのDataFrameとそれに関連するすべての警告を作成します。
df = pd.DataFrame(columns=['A', 'B', 'C'], index=range(5))
df
A B C
0 NaN NaN NaN
1 NaN NaN NaN
2 NaN NaN NaN
3 NaN NaN NaN
4 NaN NaN NaN
他のオブジェクトと同様に、オブジェクト列のDataFrameを作成します。
df.dtypes
A object # you DON'T want this
B object
C object
dtype: object
追加には、上記の方法と同様にすべての問題があります。
for i, (a, b, c) in enumerate(some_function_that_yields_data()):
df.iloc[i] = [a, b, c]
証拠はプリンにあります
これらのメソッドのタイミングは、メモリとユーティリティの点でどれだけ異なるかを確認する最も速い方法です。
参照用のベンチマークコード。