pandas DataFrameに1行追加する


870

私はパンダが完全に読み込まれたように設計されていることを理解していますが、空のDataFrameDataFrame作成してから、行を1つずつ追加する必要があります。これを行う最良の方法は何ですか?

私は空のデータフレームを正常に作成しました:

res = DataFrame(columns=('lib', 'qty1', 'qty2'))

次に、新しい行を追加して、フィールドに次のように入力します。

res = res.set_value(len(res), 'qty1', 10.0)

動作しますが非常に奇妙に見えます:-/(文字列値の追加に失敗します)

DataFrameに新しい列を追加するにはどうすればよいですか(列の種類が異なります)。


70
これは、大きなDataFrameを構築するための非常に非効率的な方法です。行を追加するときに、新しい配列を作成する(既存のデータをコピーする)必要があります。
ウェスマッキーニー

5
@WesMcKinney:Thx、知っておくと本当に良い。巨大なテーブルにを追加するのは非常に高速ですか?
最大

4
効率が悪すぎる場合は、追加の行を事前に割り当ててから更新できます。
user1154664 2013

回答:


570
>>> import pandas as pd
>>> from numpy.random import randint

>>> df = pd.DataFrame(columns=['lib', 'qty1', 'qty2'])
>>> for i in range(5):
>>>     df.loc[i] = ['name' + str(i)] + list(randint(10, size=2))

>>> df
     lib qty1 qty2
0  name0    3    3
1  name1    2    4
2  name2    2    8
3  name3    2    1
4  name4    9    6

25
メモリを事前に割り当てるためにインデックスを追加することを検討してください(私の回答を参照)
FooBar

34
@MaximG:アップグレードを強くお勧めします。現在のPandasバージョンは0.15.0です。
フレッド

44
.locがインデックス列を参照しているため、(例のように)0から始まる連続した整数のシーケンスではないインデックスを使用して既存のDataFrameを操作している場合、.loc既存の行が上書きされるか、行が挿入されます。インデックスにギャップを作成します。既存のゼロ以外の長さのデータフレームを追加するためのより堅牢な(ただし、絶対に確実ではない)アプローチはdf.loc[df.index.max() + 1] = [randint(...、次のとおりです。
ホブ、

4
@hobs df.index.max()nan、DataFrameが空の場合です。
flow2k

4
@hobs私が考えた1つの解決策は、3項演算子を使用することdf.loc[0 if pd.isnull(df.index.max()) else df.index.max() + 1]
です。– flow2k

475

データフレームのすべてのデータを事前に取得できる場合、データフレームに追加するよりもはるかに高速なアプローチがあります。

  1. 各辞書が入力データ行に対応する辞書のリストを作成します。
  2. このリストからデータフレームを作成します。

行ごとにデータフレームに追加するのに30分かかり、数秒以内に完了する辞書のリストからデータフレームを作成するという同様のタスクがありました。

rows_list = []
for row in input_rows:

        dict1 = {}
        # get input row in dictionary format
        # key = col_name
        dict1.update(blah..) 

        rows_list.append(dict1)

df = pd.DataFrame(rows_list)               

48
すべてのデータを事前に取得できない状況でも、これを行うようにしました。速度の違いは驚くべきものです。
14

47
パンダドキュメントからのコピー: It is worth noting however, that concat (and therefore append) makes a full copy of the data, and that constantly reusing this function can create a significant performance hit. If you need to use the operation over several datasets, use a list comprehension.pandas.pydata.org/pandas-docs/stable/…
thikonom

5
これはうまくいきます!データフレームを作成したときを除いて、列名の順序がすべて間違っていました...
user5359531

5
@ user5359531その場合、順序付けられたディクテーションを使用できます
ShikharDua、

21
@ user5359531列を手動で指定でき、順序は保持されます。pd.DataFrame(rows_list、columns = ['C1'、 'C​​2'、 'C​​3'])はトリックを実行します
Marcello Grechi Lins

288

pandas.concat()またはを使用できますDataFrame.append()。詳細と例については、マージ、結合、および連結を参照してください。


6
こんにちは、append()またはconcat()を使用するメソッドの答えは何ですか 私は同じ問題を抱えていますが、それを理解しようとしています。
notilas 2014

109
これは正しい答えですが、あまり良い答えではありません(ほとんどリンクのみ)。
jwg 2016年

5
@fredの答えはもっと正しいと思います。IIUCこの回答の問題は、行が追加されるたびにDataFrame全体が不必要にコピーされることです。.loc特に注意している場合は、回避できるメカニズムを使用します。
ケンウィリアムズ

7
ただし、を使用するDataFrame.append()場合は、行データがリストではなく最初にDataFrameでもあることを確認する必要があります。
StayFoolish

202

久しぶりですが、私も同じ問題に直面しました。そして、ここで興味深い答えがたくさん見つかりました。そのため、どの方法を使用するか混乱しました。

多くの行をデータフレームに追加する場合、速度パフォーマンスに関心があります。そこで、最も人気のある4つの方法を試して、その速度を確認しました。

新しいバージョンのパッケージを使用して2019年に更新されました@FooBarコメントの後にも更新

スピードパフォーマンス

  1. .appendの使用(NPEの回答
  2. .locの使用(フレッドの答え
  3. 事前割り当てで.locを使用する(FooBarの回答
  4. 最後にdictを使用してDataFrameを作成する(ShikharDuaの答え

結果(秒):

|------------|-------------|-------------|-------------|
|  Approach  |  1000 rows  |  5000 rows  | 10 000 rows |
|------------|-------------|-------------|-------------|
| .append    |    0.69     |    3.39     |    6.78     |
|------------|-------------|-------------|-------------|
| .loc w/o   |    0.74     |    3.90     |    8.35     |
| prealloc   |             |             |             |
|------------|-------------|-------------|-------------|
| .loc with  |    0.24     |    2.58     |    8.70     |
| prealloc   |             |             |             |
|------------|-------------|-------------|-------------|
|  dict      |    0.012    |   0.046     |   0.084     |
|------------|-------------|-------------|-------------|

また、有用なコメントを提供してくれた@krassowskiにも感謝します。コードを更新しました。

それで、私は自分自身のために辞書を通して加算を使います。


コード:

import pandas as pd
import numpy as np
import time

del df1, df2, df3, df4
numOfRows = 1000
# append
startTime = time.perf_counter()
df1 = pd.DataFrame(np.random.randint(100, size=(5,5)), columns=['A', 'B', 'C', 'D', 'E'])
for i in range( 1,numOfRows-4):
    df1 = df1.append( dict( (a,np.random.randint(100)) for a in ['A','B','C','D','E']), ignore_index=True)
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df1.shape)

# .loc w/o prealloc
startTime = time.perf_counter()
df2 = pd.DataFrame(np.random.randint(100, size=(5,5)), columns=['A', 'B', 'C', 'D', 'E'])
for i in range( 1,numOfRows):
    df2.loc[i]  = np.random.randint(100, size=(1,5))[0]
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df2.shape)

# .loc with prealloc
df3 = pd.DataFrame(index=np.arange(0, numOfRows), columns=['A', 'B', 'C', 'D', 'E'] )
startTime = time.perf_counter()
for i in range( 1,numOfRows):
    df3.loc[i]  = np.random.randint(100, size=(1,5))[0]
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df3.shape)

# dict
startTime = time.perf_counter()
row_list = []
for i in range (0,5):
    row_list.append(dict( (a,np.random.randint(100)) for a in ['A','B','C','D','E']))
for i in range( 1,numOfRows-4):
    dict1 = dict( (a,np.random.randint(100)) for a in ['A','B','C','D','E'])
    row_list.append(dict1)

df4 = pd.DataFrame(row_list, columns=['A','B','C','D','E'])
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df4.shape)

PS私の考えでは、私の認識は完璧ではなく、おそらく最適化が行われています。


4
df2.index.max()forを.loc不必要に使用すると、計算が複雑になります。単純なdf2.loc[i] = ...ことでしょう。私にとっては、時間を10秒から8.64秒に短縮しました
クラスソウスキー

テストで私のアプローチに従っていないので、リストから私の名前を削除してください。適切なサイズのインデックスを提供してメモリを事前に割り当てていません。
FooBar

@FooBarこんにちは!作者が私の答えを見たとき、私はあなたに嬉しいです:)あなたは正しいです、私はこの重要なポイントを逃しました。あなたのアプローチは異なる結果を示すので、私は結果テーブルにもう1行追加することを好みます!
Mikhail_Sam

@Mikhail_Samピボットテーブルを使用して、最速の方法であるdictを使用してExcelファイルに書き込むにはどうしますか?
FabioSpaghetti、

1
Dict to Pandas DataFrameがより良い方法である理由について別のコメントを投げたかっただけです。テーブルに複数の異なるデータ型があるデータセットを使った実験では、Pandasのappendメソッドを使用すると型付けが破棄されますが、Dictを使用してDataFrameを一度だけ作成すると、元のデータ型はそのまま保持されます。
trumpetlicks

109

事前にエントリ数がわかっている場合は、インデックスも提供してスペースを事前に割り当てる必要があります(別の回答からデータの例を取り上げます)。

import pandas as pd
import numpy as np
# we know we're gonna have 5 rows of data
numberOfRows = 5
# create dataframe
df = pd.DataFrame(index=np.arange(0, numberOfRows), columns=('lib', 'qty1', 'qty2') )

# now fill it up row by row
for x in np.arange(0, numberOfRows):
    #loc or iloc both work here since the index is natural numbers
    df.loc[x] = [np.random.randint(-1,1) for n in range(3)]
In[23]: df
Out[23]: 
   lib  qty1  qty2
0   -1    -1    -1
1    0     0     0
2   -1     0    -1
3    0    -1     0
4   -1     0     0

速度比較

In[30]: %timeit tryThis() # function wrapper for this answer
In[31]: %timeit tryOther() # function wrapper without index (see, for example, @fred)
1000 loops, best of 3: 1.23 ms per loop
100 loops, best of 3: 2.31 ms per loop

そして、コメントからわかるように、サイズが6000の場合、速度の違いはさらに大きくなります。

配列のサイズ(12)と行の数(500)を増やすと、速度の違いがより顕著になります:313ms対2.29s


3
すばらしい答えです。これは、行スペースが段階的に割り当てられる必要がないようにするための基準です。
2014年

8
配列のサイズ(12)と行の数(500)を増やすと、速度の違いがより顕著になります:313ms vs 2.29s
Tickon

80
mycolumns = ['A', 'B']
df = pd.DataFrame(columns=mycolumns)
rows = [[1,2],[3,4],[5,6]]
for row in rows:
    df.loc[len(df)] = row

2
この!私はずっと探していましたが、これは特定の値を行に割り当てる方法を実際に示す最初の投稿です!おまけの質問:列名/値のペアの構文はどれですか?それは辞書を使ったものに違いないと思いますが、正しく理解できていないようです。
jhin 2016年

3
拡張すると実際にDataFrame全体がコピーされるため、これは効率的ではありません。
防水

72

効率的な追加については、「パンダデータフレームに行を追加する方法」および「拡大して設定する」を参照してください。

存在loc/ixないキーインデックスデータに行を追加します。例:

In [1]: se = pd.Series([1,2,3])

In [2]: se
Out[2]: 
0    1
1    2
2    3
dtype: int64

In [3]: se[5] = 5.

In [4]: se
Out[4]: 
0    1.0
1    2.0
2    3.0
5    5.0
dtype: float64

または:

In [1]: dfi = pd.DataFrame(np.arange(6).reshape(3,2),
   .....:                 columns=['A','B'])
   .....: 

In [2]: dfi
Out[2]: 
   A  B
0  0  1
1  2  3
2  4  5

In [3]: dfi.loc[:,'C'] = dfi.loc[:,'A']

In [4]: dfi
Out[4]: 
   A  B  C
0  0  1  0
1  2  3  2
2  4  5  4
In [5]: dfi.loc[3] = 5

In [6]: dfi
Out[6]: 
   A  B  C
0  0  1  0
1  2  3  2
2  4  5  4
3  5  5  5

ユーザーは実装を要求しました(新しい行を追加)。ここでは、定義されたインデックスに行を追加する方法または列を追加する方法を示します。
ギルヘルムフェリペレイス

1
これがdictメソッドと比較してどのように機能するかについてのベンチマーク
PirateApp

実際にはDataFrame全体をコピーするため、これは効率的ではありません。
防水

66

ignore_indexオプションを使用して、辞書として単一の行を追加できます。

>>> f = pandas.DataFrame(data = {'Animal':['cow','horse'], 'Color':['blue', 'red']})
>>> f
  Animal Color
0    cow  blue
1  horse   red
>>> f.append({'Animal':'mouse', 'Color':'black'}, ignore_index=True)
  Animal  Color
0    cow   blue
1  horse    red
2  mouse  black

37
f.append(<stuff>)単に現在のオブジェクトに追加するのではなく、新しいオブジェクトを作成することにも言及するかもしれません。したがって、スクリプトのデータフレームに追加しようとしている場合は、次のように言う必要がありますf = f.append(<stuff>)
Blairg23

2
これを行う方法はありますか?

@笑いません。github.com/pandas-dev/pandas/issues/2801を参照してください-配下の配列は拡張できないため、コピーする必要があります。
防水

46

Pythonicの方法のために、ここに私の答えを追加します。

res = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))
res = res.append([{'qty1':10.0}], ignore_index=True)
print(res.head())

   lib  qty1  qty2
0  NaN  10.0   NaN

27

リストのリストを作成してデータフレームに変換することもできます-

import pandas as pd

columns = ['i','double','square']
rows = []

for i in range(6):
    row = [i, i*2, i*i]
    rows.append(row)

df = pd.DataFrame(rows, columns=columns)

与える

    私はダブルスクエア
0 0 0 0
1 1 2 1
2 2 4 4
3 3 6 9
4 4 8 16
5 5 10 25

15

これはOPの質問への回答ではなく、@ ShikharDuaの回答を説明するおもちゃの例です。

このフラグメントは取るに足らないものですが、実際のデータには1,000行と多くの列があり、さまざまな列でグループ化して、複数のタジェット列に対して以下の統計を実行できるようにしたいと考えました。したがって、一度に1行ずつデータフレームを構築するための信頼できる方法があることは、非常に便利でした。@ShikharDuaありがとうございます!

import pandas as pd 

BaseData = pd.DataFrame({ 'Customer' : ['Acme','Mega','Acme','Acme','Mega','Acme'],
                          'Territory'  : ['West','East','South','West','East','South'],
                          'Product'  : ['Econ','Luxe','Econ','Std','Std','Econ']})
BaseData

columns = ['Customer','Num Unique Products', 'List Unique Products']

rows_list=[]
for name, group in BaseData.groupby('Customer'):
    RecordtoAdd={} #initialise an empty dict 
    RecordtoAdd.update({'Customer' : name}) #
    RecordtoAdd.update({'Num Unique Products' : len(pd.unique(group['Product']))})      
    RecordtoAdd.update({'List Unique Products' : pd.unique(group['Product'])})                   

    rows_list.append(RecordtoAdd)

AnalysedData = pd.DataFrame(rows_list)

print('Base Data : \n',BaseData,'\n\n Analysed Data : \n',AnalysedData)

14

シンプルで良い方法を考え出した:

>>> df
     A  B  C
one  1  2  3
>>> df.loc["two"] = [4,5,6]
>>> df
     A  B  C
one  1  2  3
two  4  5  6

1
これにより、DataFrame全体が内部でコピーされることに注意してください。基になる配列は拡張できないため、コピーする必要があります。
防水

10

ジェネレーターオブジェクトを使用してDataframeを作成できます。これにより、リスト全体のメモリ効率が向上します。

num = 10

# Generator function to generate generator object
def numgen_func(num):
    for i in range(num):
        yield ('name_{}'.format(i), (i*i), (i*i*i))

# Generator expression to generate generator object (Only once data get populated, can not be re used)
numgen_expression = (('name_{}'.format(i), (i*i), (i*i*i)) for i in range(num) )

df = pd.DataFrame(data=numgen_func(num), columns=('lib', 'qty1', 'qty2'))

既存のDataFrameにrawを追加するには、appendメソッドを使用できます。

df = df.append([{ 'lib': "name_20", 'qty1': 20, 'qty2': 400  }])

9

新しいレコード(データフレーム)を作成し、old_data_frameに追加します値の
リストと対応する名を渡して、new_record(data_frame)を作成します

new_record = pd.DataFrame([[0,'abcd',0,1,123]],columns=['a','b','c','d','e'])

old_data_frame = pd.concat([old_data_frame,new_record])

8

ここに行を追加/追加する方法です pandas DataFrame

def add_row(df, row):
    df.loc[-1] = row
    df.index = df.index + 1  
    return df.sort_index()

add_row(df, [1,2,3]) 

空のまたは入力済みのパンダDataFrameに行を挿入/追加するために使用できます


1
これは降順でインデックスを追加します
パルチバンラジェンドラン

5

ShikharDuaの答えのように辞書のリストの代わりに、テーブルをリストの辞書として表すこともできます。列が事前にわかっている場合、各リストは1つの列を行順に格納します。最後に、DataFrameを一度構築します。

以下のためのC列とN行、この用途1つの辞書とCリスト、1つのリストと対Nの辞書。辞書のリスト方式では、各辞書にすべてのキーが格納されており、すべての行に新しい辞書を作成する必要があります。ここでは、リストに追加するだけです。これは一定の時間で、理論的には非常に高速です。

# current data
data = {"Animal":["cow", "horse"], "Color":["blue", "red"]}

# adding a new row (be careful to ensure every column gets another value)
data["Animal"].append("mouse")
data["Color"].append("black")

# at the end, construct our DataFrame
df = pd.DataFrame(data)
#   Animal  Color
# 0    cow   blue
# 1  horse    red
# 2  mouse  black

5

最後に行を追加する場合は、リストとして追加します

valuestoappend = [va1,val2,val3]
res = res.append(pd.Series(valuestoappend,index = ['lib', 'qty1', 'qty2']),ignore_index = True)

4

それを行う別の方法(おそらくあまりパフォーマンスが良くない):

# add a row
def add_row(df, row):
    colnames = list(df.columns)
    ncol = len(colnames)
    assert ncol == len(row), "Length of row must be the same as width of DataFrame: %s" % row
    return df.append(pd.DataFrame([row], columns=colnames))

次のようにDataFrameクラスを拡張することもできます。

import pandas as pd
def add_row(self, row):
    self.loc[len(self.index)] = row
pd.DataFrame.add_row = add_row

1

それを簡単に。データフレームの行として追加される入力としてリストを取得することにより:-

import pandas as pd  
res = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))  
for i in range(5):  
    res_list = list(map(int, input().split()))  
    res = res.append(pd.Series(res_list,index=['lib','qty1','qty2']), ignore_index=True)

1

必要なのはloc[df.shape[0]]またはloc[len(df)]


# Assuming your df has 4 columns (str, int, str, bool)
df.loc[df.shape[0]] = ['col1Value', 100, 'col3Value', False] 

または

df.loc[len(df)] = ['col1Value', 100, 'col3Value', False] 

0

df.loc[subscript] = …1つのDataFrame行に割り当てる構成がよく見られます。Mikhail_Samが投稿したベンチマークには、このコンストラクトと、最後にdictとcreate DataFrameを使用するメソッドが含まれています。彼は後者が断然最速であることを発見しました。しかしdf3.loc[i] = …、彼のコードの(事前に割り当てられたDataFrameで)をに置き換えるとdf3.values[i] = …、結果は大幅に変わります。したがって、私たちはより頻繁にの使用df.values[subscript] = …を考慮する必要があります。ただし.values、それはDataFrame.indexとは異なる可能性があるゼロベースの添え字を取ることに注意してください。


これのコード例は有用でしょう
baxx

1
@baxx-1つのコード例ベンチマークリンク(# .loc with prealloc)にあり、別の例はPandas DataFrameの各行のデータを残りの行のデータと比較する必要があります。計算を高速化する方法があります。 ?そしてその受け入れられた答え。
アルマリ

0

pandas.DataFrame.append

DataFrame.append(self、other、ignore_index = False、verify_integrity = False、sort = False)→ 'DataFrame'

df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
df2 = pd.DataFrame([[5, 6], [7, 8]], columns=list('AB'))
df.append(df2)

ignore_indexをTrueに設定した場合:

df.append(df2, ignore_index=True)

0

行を追加する前に、データフレームをディクショナリに変換する必要があります。ここで、キーをデータフレームの列として見ることができ、列の値はディクショナリに再度格納されますが、すべての列のキーはデータフレームのインデックス番号です。その考えは私に以下のコードを書くようにさせます。

df2=df.to_dict()
values=["s_101","hyderabad",10,20,16,13,15,12,12,13,25,26,25,27,"good","bad"] #this is total row that we are going to add
i=0
for x in df.columns:   #here df.columns gives us the main dictionary key
    df2[x][101]=values[i]   #here the 101 is our index number it is also key of sub dictionary
    i+=1

0

このために2つのデータフレームを連結できます。私は基本的にこの問題に遭遇し、新しい行を既存のDataFrameに文字インデックス(数値ではない)で追加しました。そこで、新しい行のデータをduct()に入力し、インデックスをリストに入力します。

new_dict = {put input for new row here}
new_list = [put your index here]

new_df = pd.DataFrame(data=new_dict, index=new_list)

df = pd.concat([existing_df, new_df])

-1

これにより、空のDataFrameにアイテムが追加されます。問題はdf.index.max() == nan、最初のインデックスの場合です。

df = pd.DataFrame(columns=['timeMS', 'accelX', 'accelY', 'accelZ', 'gyroX', 'gyroY', 'gyroZ'])

df.loc[0 if math.isnan(df.index.max()) else df.index.max() + 1] = [x for x in range(7)]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.