在pandas DataFrame中添加一行

PhE 731 python append dataframe pandas

我知道pandas旨在加载完全填充DataFrame但我需要创建一个空的DataFrame,然后逐个添加行.做这个的最好方式是什么 ?

我成功创建了一个空的DataFrame:

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

然后我可以添加一个新行并填充一个字段:

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

它工作但似乎很奇怪: - /(它添加字符串值失败)

如何向我的DataFrame添加新行(具有不同的列类型)?

fred.. 466

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

  • @MaximG:我强烈建议升级.目前的熊猫版本是0.15.0. (34认同)
  • `.loc`正在引用索引列,所以如果你正在处理一个预先存在的DataFrame,其索引不是以0开头的连续整数序列(如你的例子),`.loc`将覆盖现有行或插入行,或在索引中创建间隙.用于附加现有非零长度数据帧的更强大(但不是万无一失的)方法是:`df.loc [df.index.max()+ 1] = [randint(...`或预填充索引为@FooBar建议. (33认同)
  • 考虑添加索引以预分配内存(请参阅我的回答) (21认同)
  • 当DataFrame为空时,@hobs`df.index.max()`是`nan`。 (3认同)
  • @hobs:我完全同意你的看法.感谢您的输入.但是,它与原始问题中提出的情况不同.如果您事先了解数据框的大小,那么分配内存肯定会更快. (2认同)
  • @ flow2k好抓!我能想到的唯一解决方案是尝试接受pd.DataFrame()构造函数调用(仅在第一行插入)。你知道更好的方法吗? (2认同)
  • @hobs我想到的一种解决方案是使用三元运算符:df.loc [0,如果pd.isnull(df.index.max())否则df.index.max()+ 1]` (2认同)

ShikharDua.. 378

如果您可以预先获取数据帧的所有数据,则可以采用比附加到数据框更快的方法:

  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)               

  • 对于我无法预先获得所有数据的任何情况,我已经开始这样做了.速度差异令人惊讶. (38认同)
  • 从pandas docs复制:"值得注意的是,concat(因此追加)会生成数据的完整副本,并且不断重用此函数会产生重大的性能损失.如果您需要对多个数据集使用该操作,请使用列表推导.(http://pandas.pydata.org/pandas-docs/stable/merging.html#concatenating-objects) (36认同)
  • @ user5359531您可以手动指定列,并保留订单.pd.DataFrame(rows_list,columns = ['C1','C2','C3'])会做的伎俩 (16认同)
  • 这很棒!除了我创建数据框外,列名都是错误的顺序...... (5认同)
  • @ user5359531在这种情况下你可以使用有序的dict (5认同)

NPE.. 265

你可以使用pandas.concat()DataFrame.append().有关详细信息和示例,请参阅合并,连接和连接.

  • 这是正确的答案,但它不是一个非常好的答案(几乎只是链接). (86认同)
  • 嗨,那么使用append()或concat()的方法的答案是什么.我有同样的问题,但仍然试图搞清楚. (6认同)
  • 但是如果你想使用`DataFrame.append()`,你必须首先确保你的行数据也是一个DataFrame,而不是列表. (5认同)
  • 我认为@fred的答案更为正确.IIUC这个答案的问题是每次附加一行时它会不必要地复制整个DataFrame.使用可以避免的`.loc`机制,特别是如果你小心的话. (4认同)

Mikhail_Sam.. 131

已经很久了,但我也遇到了同样的问题.并在这里找到了很多有趣的答案.所以我很困惑使用什么方法.

在向数据帧添加大量行的情况下,我对速度性能感兴趣.所以我尝试了3种最流行的方法并检查了它们的速度.

使用新版本的软件包在2019年更新

速度表现

  1. 使用.append(NPE的答案)
  2. 使用.loc(fred的答案FooBar的答案)
  3. 最后使用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我相信,我的认识并不完美,也许有一些优化.

  • 在.loc中使用df2.index.max()不必要地增加了计算复杂度。简单的`df2.loc [i] = ...`就可以了。对我来说,时间从10秒减少到8.64秒 (3认同)

FooBar.. 96

如果您事先知道条目数,则应通过提供索引来预先分配空间(从不同答案中获取数据示例):

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 vs 2.29s

  • 增加阵列(12)的大小和行数(500)会使速度差异更加显着:313ms vs 2.29s (7认同)
  • 很好的答案.这应该是常态,因此行空间不必逐步分配. (3认同)

Lydia.. 69

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认同)
  • 这效率不高,因为它在扩展时实际上会复制整个DataFrame。 (2认同)

Nasser Al-Wo.. 67

有效追加请参阅如何向pandas数据框添加额外行使用放大设置.

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


W.P. McNeill.. 57

您可以使用该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

  • 你可能还会提到`f.append(<stuff>)`创建一个新对象,而不是简单地附加到当前对象,所以如果你试图追加到脚本中的数据帧,你需要说`f = f.append(<stuff>)` (31认同)
  • 有没有办法做到这一点? (2认同)

hkyi.. 41

为了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


Brian Burns.. 19

您还可以构建列表列表并将其转换为数据框 -

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)

    i   double  square
0   0   0   0
1   1   2   1
2   2   4   4
3   3   6   9
4   4   8   16
5   5   10  25


小智.. 14

这不是OP问题的答案,而是一个玩具示例来说明@ShikharDua的答案,我发现它非常有用.

虽然这个片段是微不足道的,但在实际数据中我有1,000行和多列,我希望能够按不同的列进行分组,然后对多个taget列执行下面的统计.因此,一次一行地构建数据帧的可靠方法是非常方便的.谢谢@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)


Qinsi.. 13

想出一个简单而好的方法:

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


Jack Daniel.. 8

创建一个新记录(数据框)并添加到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])


小智.. 5

这是在熊猫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中插入/追加一行


归档时间:

查看次数:

1076557 次

最近记录:

9 月,3 周 前