web-dev-qa-db-ja.com

空のPandas DataFrameを作成し、それを埋めますか?

私はここのパンダDataFrameドキュメントから始めています: http://pandas.pydata.org/pandas-docs/stable/dsintro.html

時系列の計算で、DataFrameに値を繰り返し入力します。そのため、基本的に、列A、B、タイムスタンプ行(すべて0、すべてNaN)を使用してDataFrameを初期化します。

それから私は初期値を追加し、前の行から新しい行を計算するためにこのデータを調べます、row[A][t] = row[A][t-1]+1と言います。

私は現在以下のようにコードを使用していますが、私はそれがちょっと醜いと感じていて、直接DataFrameでこれをする方法、または一般的にちょうど良い方法があるに違いない。注:私はPython 2.7を使っています。

import datetime as dt
import pandas as pd
import scipy as s

if __== '__main__':
    base = dt.datetime.today().date()
    dates = [ base - dt.timedelta(days=x) for x in range(0,10) ]
    dates.sort()

    valdict = {}
    symbols = ['A','B', 'C']
    for symb in symbols:
        valdict[symb] = pd.Series( s.zeros( len(dates)), dates )

    for thedate in dates:
        if thedate > dates[0]:
            for symb in valdict:
                valdict[symb][thedate] = 1+valdict[symb][thedate - dt.timedelta(days=1)]

    print valdict
315
Matthias Kauer

ここにいくつかの提案があります:

インデックスに date_range を使用します。

import datetime
import pandas as pd
import numpy as np

todays_date = datetime.datetime.now().date()
index = pd.date_range(todays_date-datetime.timedelta(10), periods=10, freq='D')

columns = ['A','B', 'C']

注:(NaNsを指定して)空のDataFrameを作成することもできます。

df_ = pd.DataFrame(index=index, columns=columns)
df_ = df_.fillna(0) # with 0s rather than NaNs

データに対してこれらのタイプの計算を行うには、テンキー配列を使用します。

data = np.array([np.arange(10)]*3).T

したがって、私たちはDataFrameを作成することができます。

In [10]: df = pd.DataFrame(data, index=index, columns=columns)

In [11]: df
Out[11]: 
            A  B  C
2012-11-29  0  0  0
2012-11-30  1  1  1
2012-12-01  2  2  2
2012-12-02  3  3  3
2012-12-03  4  4  4
2012-12-04  5  5  5
2012-12-05  6  6  6
2012-12-06  7  7  7
2012-12-07  8  8  8
2012-12-08  9  9  9
249
Andy Hayden

後で空のデータフレームを作成し、後でそれを受信データフレームで埋めたい場合は、これを試してください。

この例では、 this pandas doc を使用して新しいデータフレームを作成し、次に append を使用してoldDFのデータを使用してnewDFに書き込みます。


これを見てください

newDF = pd.DataFrame() #creates a new dataframe that's empty
newDF = newDF.append(oldDF, ignore_index = True) # ignoring index is optional
# try printing some data from newDF
print newDF.head() #again optional 
  • 私がこのnewDFに複数のoldDFから新しいデータを追加し続ける必要がある場合は、forループを使用して pandas.DataFrame.append() を繰り返します。
118
geekidharsh

最初からカラム名を配置したい場合は、次の方法を使用します。

import pandas as pd

col_names =  ['A', 'B', 'C']
my_df  = pd.DataFrame(columns = col_names)
my_df

データフレームにレコードを追加したい場合は、それを使用することをお勧めします。

my_df.loc[len(my_df)] = [2, 4, 5]

また、辞書を渡したくなるかもしれません。

my_dic = {'A':2, 'B':4, 'C':5}
my_df.loc[len(my_df)] = my_dic 

my_dfに別のデータフレームを追加したい場合は、次のようにします。

col_names =  ['A', 'B', 'C']
my_df2  = pd.DataFrame(columns = col_names)
my_df = my_df.append(my_df2)

ループ内に行を追加する場合は、パフォーマンスの問題を考慮してください。
最初の1000レコード前後では "my_df.loc"のパフォーマンスは良くなり、ループ内のレコード数を増やすと徐々に遅くなります。

大きなループの中で薄くすることを計画している場合(たとえば、10Mレコード程度)
あなたはこれら二つの混合物を使うほうがいいです。サイズが約1000になるまでデータフレームをilocで埋めてから、元のデータフレームに追加して、一時データフレームを空にします。これにより、パフォーマンスが約10倍向上します。

85
Afshin Amiri

DataFrameを作成するRight Way™

ここでのほとんどの回答は、空の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(またはNaNの1つ)を作成して繰り返し追加するよりも、リストに追加してDataFrameを一度に作成する方が常に安価です。 リストはより少ないメモリを使用し、使用するデータ構造がはるかに軽い、追加、削除(必要な場合)。

この方法のもう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で一度に連結することです。

df.appendに関連するもう1つの間違いは、ユーザーが追加はインプレース関数ではないを忘れがちであるため、結果を割り当てる必要があることです。また、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

pandasはオブジェクト列の操作をベクトル化できないため、オブジェクト列の処理は決して良いことではありません。修正するにはこれを行う必要があります。

df.infer_objects().dtypes
A      int64
B    float64
C     object
dtype: object

ループ内のloc

空に作成されたDataFrameに追加するために使用されるlocも見ました。

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と同じくらい悪く、さらにbadいです。

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]

証拠はプリンにあります

これらのメソッドのタイミングは、メモリとユーティリティの点でどれだけ異なるかを確認する最も速い方法です。

enter image description here

参照用のベンチマークコード

24
cs95