我如何创建一个空DataFrame,然后添加行,一个接一个?
我创建了一个空DataFrame:
df = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))
然后我可以在最后添加一个新行,并填充一个字段:
df = df._set_value(index=len(df), col='qty1', value=10.0)
它一次只适用于一个领域。向df中添加新行有什么更好的方法?
我如何创建一个空DataFrame,然后添加行,一个接一个?
我创建了一个空DataFrame:
df = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))
然后我可以在最后添加一个新行,并填充一个字段:
df = df._set_value(index=len(df), col='qty1', value=10.0)
它一次只适用于一个领域。向df中添加新行有什么更好的方法?
当前回答
简单点。通过将一个列表作为输入,该列表将作为一行添加到数据帧中:
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)
其他回答
我们经常看到结构df。loc[下标]=…分配给一个数据帧行。Mikhail_Sam发布了包含这个构造以及使用dict并最终创建DataFrame的方法的基准测试。他发现后者是目前为止最快的。
但是如果我们替换df3。loc[i] =…(与预分配的DataFrame)在他的代码df3。值[i] =…时,结果会发生显著变化,因为该方法的执行与使用dict的方法类似。所以我们应该经常使用df。考虑[下标]=…但是请注意,.values有一个从零开始的下标,这可能与DataFrame.index不同。
如果你事先知道条目的数量,你应该通过提供索引来预分配空间(从不同的答案中获得数据示例):
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)使 速度上的差异更加显著:313毫秒vs 2.29秒
如果你想在末尾添加一行,将其作为列表追加:
valuestoappend = [va1, val2, val3]
res = res.append(pd.Series(valuestoappend, index = ['lib', 'qty1', 'qty2']), ignore_index = True)
永远不要增长数据框架!
是的,人们已经解释了,你不应该增长一个DataFrame,你应该追加你的数据到一个列表,并转换为一个DataFrame一旦结束。但你知道为什么吗?
以下是最重要的原因,摘自我在这里的帖子。
它总是更便宜/更快地追加到一个列表和创建一个DataFrame。 列表占用更少的内存,并且是一种更轻的数据结构,可以处理、添加和删除。 为您的数据自动推断d类型。另一方面,创建一个空的nan帧将自动使它们成为对象,这是不好的。 索引是自动为您创建的,而不是您必须小心地将正确的索引分配给您追加的行。
这是正确的方式™积累您的数据
data = []
for a, b, c in some_function_that_yields_data():
data.append([a, b, c])
df = pd.DataFrame(data, columns=['A', 'B', 'C'])
这些选择都很糟糕
在循环内追加或连接 Append和concat单独在本质上并不坏。的 当您在循环中迭代调用它们时,问题就开始了 结果在二次内存使用。 #创建空数据框架并追加 Df = pd。DataFrame(columns=['A', 'B', 'C']) 对于some_function_that_yields_data()中的a, b, c: Df = Df。追加({A:我,B: B, C: C}, ignore_index = True) #这同样糟糕: # df = pd.concat( # df, pd。({'A': i, 'B': B, 'C': C})], # ignore_index = True) 清空nan的数据帧 永远不要创建nan的数据帧,因为列是初始化的 对象(缓慢的、不可向量化的dtype)。 #创建nan的数据帧并覆盖值。 Df = pd。DataFrame(列= [' A ', ' B ', ' C '],指数=范围(5)) 对于some_function_that_yields_data()中的a, b, c: df.loc[len(df)] = [a, b, c]
见分晓
对这些方法进行计时是了解它们在内存和效用方面有多大不同的最快方法。
基准测试代码供参考。
像这样的帖子提醒了我为什么我是这个社区的一员。人们明白教人们用正确的代码得到正确答案的重要性,而不是用错误的代码得到正确答案。现在,您可能会争辩说,如果您只是向DataFrame添加一行,那么使用loc或append都不是问题。然而,人们经常会在这个问题上添加不止一行——通常要求是使用来自函数的数据在循环中迭代地添加一行(参见相关问题)。在这种情况下,重要的是要理解迭代增长DataFrame不是一个好主意。
您可以为此连接两个数据框架。我基本上遇到了这个问题,用字符索引(不是数字)向现有的DataFrame添加新行。
因此,我在一个管道()中输入新行数据,并在一个列表中索引。
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])