725

私はここでパンダの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を直接使用する方法、または一般的にはもっと良い方法が必要です。注:私はPython2.7を使用しています。

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

if __name__ == '__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
4

7 に答える 7

685

DataFrameを成長させないでください!

TLDR; (太字のテキストを読んでください)

ここでのほとんどの回答は、空のDataFrameを作成して記入する方法を示していますが、それが悪いことであるとは誰も教えてくれません。

これが私のアドバイスです:DataFrameではなくリストにデータを蓄積します。

リストを使用してデータを収集し、準備ができたらDataFrameを初期化します。list-of-listsまたはlist-of-dicts形式のいずれかが機能し、pd.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'])

このアプローチの長所:

  1. 空のDataFrame(またはNaNの1つ)を作成して何度も追加するよりも、リストに追加してDataFrameを一度に作成する方が常に安価です。

  2. リストはまた、より少ないメモリを使用し、操作、追加、および削除(必要な場合)するためのはるかに軽いデータ構造です。

  3. dtypesobject(それらすべてに割り当てるのではなく)自動的に推測されます。

  4. RangeIndex各反復で追加する行に正しいインデックスを割り当てるように注意する必要はなく、データに対してAが自動的に作成されます。

まだ確信が持てない場合は、ドキュメントにも記載されています。

DataFrameに行を繰り返し追加すると、単一の連結よりも計算量が多くなる可能性があります。より良い解決策は、それらの行をリストに追加してから、リストを元のDataFrameと一度に連結することです。

しかし、関数が1つの大きなDataFrameに結合する必要がある小さなDataFrameを返す場合はどうなりますか?

それでも問題ありません。小さいDataFrameのPythonリストを拡大または作成してから、を呼び出すことで、線形時間でこれを行うことができますpd.concat

small_dfs = []
for small_df in some_function_that_yields_dataframes():
    small_dfs.append(small_df)

large_df = pd.concat(small_dfs, ignore_index=True)

または、より簡潔に:

large_df = pd.concat(
    list(some_function_that_yields_dataframes()), ignore_index=True)


これらのオプションはひどいです

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次の複雑さの操作ができます。

関連するもう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]


証拠はプリンにあります

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

ここに画像の説明を入力してください

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

于 2019-06-25T02:51:37.393 に答える
410

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

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']

注:次のように記述するだけで、空のDataFrame(NaNsを使用)を作成できます。

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

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

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
于 2012-12-09T09:40:46.303 に答える
218

単に空のデータフレームを作成し、後でいくつかの着信データフレームで埋めたい場合は、次のことを試してください。

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 

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

複数のoldDFからこのnewDFに新しいデータを追加し続ける必要がある場合は、forループを使用して pandas.DataFrame.append()を反復処理します。

于 2017-01-08T04:18:18.757 に答える
157

列名で空のフレームを初期化します

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 

既存のフレームに別のフレームを追加します

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

パフォーマンスに関する考慮事項

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

大きなループ(たとえば、10M‌レコードなど)内でシンを実行する場合は、これら2つを組み合わせて使用​​することをお勧めします。サイズが約1000になるまでデータフレームをilocで埋めてから、元のデータフレームに追加し、一時データフレームを空にします。これにより、パフォーマンスが約10倍向上します。

于 2018-04-23T05:29:03.840 に答える
1

単に:

import numpy as np
import pandas as pd

df=pd.DataFrame(np.zeros([rows,columns])

それからそれを埋めます。

于 2021-10-19T16:59:51.653 に答える
0

19行のデータフレームを想定します

index=range(0,19)
index

columns=['A']
test = pd.DataFrame(index=index, columns=columns)

列Aを一定に保つ

test['A']=10

列bをループによって与えられる変数として保持する

for x in range(0,19):
    test.loc[[x], 'b'] = pd.Series([x], index = [x])

最初のxpd.Series([x], index = [x])を任意の値に置き換えることができます

于 2018-08-29T11:06:28.697 に答える
0

これは、ループを使用して複数のリストから動的データフレームを作成する方法です。

x = [1,2,3,4,5,6,7,8]
y = [22,12,34,22,65,24,12,11]
z = ['as','ss','wa', 'ss','er','fd','ga','mf']
names = ['Bob', 'Liz', 'chop']

ループ

def dataF(x,y,z,names):
    res = []

    for t in zip(x,y,z):
        res.append(t)

    return pd.DataFrame(res,columns=names)

結果

dataF(x,y,z,names)

ここに画像の説明を入力してください

于 2021-05-24T14:30:46.207 に答える