ChatGPT解决这个技术问题 Extra ChatGPT

通过一次追加一行来创建 Pandas 数据框

如何创建一个空的 DataFrame,然后一一添加行?

我创建了一个空的 DataFrame

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

然后我可以在最后添加一个新行并用以下内容填充单个字段:

df = df._set_value(index=len(df), col='qty1', value=10.0)

它一次只适用于一个领域。向 df 添加新行的更好方法是什么?

请注意,这是构建大型 DataFrame 的一种非常低效的方法;追加一行时,必须创建新数组(复制现有数据)。
@WesMcKinney:谢谢,很高兴知道。向大表添加列是否非常快?
如果它对您来说效率太低,您可以预先分配一个额外的行然后更新它。
嘿你......是的,......我明白你在做什么......你想在循环中运行它并迭代地将行添加到一个空的DataFrame,不是吗? ...嗯,don't!
我可能理解这通常是错误的,但是实时处理呢?所以说我每秒都有一些数据,我有一个线程只想填充一个数据帧,并有另一个基于偶数的线程来查看数据帧?我发现此用例有效,并且该解决方案适用于

f
fred

您可以使用 df.loc[i],其中索引为 i 的行将是您在数据框中指定的行。

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

考虑将索引添加到预分配内存(请参阅我的答案)
.loc 正在引用索引列,因此如果您使用的索引不是以 0 开头的连续整数序列(如您的示例中所示)的预先存在的 DataFrame,则 .loc 将覆盖现有行,或插入行,或在索引中创建间隙。附加现有非零长度数据帧的更强大(但不是万无一失)的方法是:df.loc[df.index.max() + 1] = [randint(... 或按照@FooBar 的建议预填充索引。
当 DataFrame 为空时,@hobs df.index.max()nan
@flow2k 好收获!我能想到的唯一解决方案是使用 pd.DataFrame() 构造函数调用尝试接受(仅在第一行插入时)。你知道更好的方法吗?
@hobs 我想到的一种解决方案是使用三元运算符:df.loc[0 if pd.isnull(df.index.max()) else df.index.max() + 1]
S
SergiyKolesnikov

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

创建一个字典列表,其中每个字典对应一个输入数据行。从此列表创建一个数据框。

我有一个类似的任务,逐行附加到数据帧需要 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)               

对于无法预先获取所有数据的任何情况,我也开始这样做。速度差异是惊人的。
从 pandas 文档复制: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/…)
这很好用!除了我创建数据框时,列名的顺序都是错误的......
@user5359531 在这种情况下,您可以使用有序 dict
@user5359531 您可以手动指定列并保留顺序。 pd.DataFrame(rows_list, columns=['C1', 'C2','C3']) 可以解决问题
P
Peter Mortensen

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

表现

使用 .append(NPE 的回答) 使用 .loc(fred 的回答) 使用 .loc 进行预分配(FooBar 的回答) 使用 dict 并最终创建 DataFrame(ShikharDua 的回答)

运行时结果(以秒为单位):

接近 1000 行 5000 行 10 000 行 .append 0.69 3.39 6.78 .loc without prealloc 0.74 3.90 8.35 .loc with prealloc 0.24 2.58 8.70 dict 0.012 0.046 0.084

所以我自己通过字典使用加法。

代码:

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:我相信我的实现并不完美,也许可以做一些优化。


df2.index.max() 用于 .loc 会不必要地增加计算复杂性。简单的 df2.loc[i] = ... 就可以了。对我来说,它将时间从 10 秒减少到 8.64 秒
请从列表中删除我的名字,因为您在测试中没有遵循我的方法:您没有通过提供合适大小的索引来预分配内存。
@FooBar 嗨!当作者看到我的回答时,我很高兴你:) 你是对的,我错过了这一点。我更喜欢为我的结果表添加一行,因为您的方法显示了不同的结果!
@Mikhail_Sam 对于最后一种 dict 方法,使用两个循环 for i in range (0,5):for i in range( 1,numOfRows-4): 背后的基本原理是什么?
只是想就为什么 Dict to Pandas DataFrame 是一种更好的方法发表另一条评论。在我对表中具有多种不同数据类型的数据集进行的实验中,使用 Pandas 附加方法会破坏类型,而使用 Dict 并且仅从它创建一次 DataFrame,似乎可以保持原始数据类型的完整性。
M
Michael WS

您可以使用 pandas.concat()DataFrame.append()。有关详细信息和示例,请参阅 Merge, join, and concatenate


嗨,那么使用 append() 或 concat() 的方法的答案是什么。我有同样的问题,但仍在努力解决。
这是正确的答案,但不是一个很好的答案(几乎只有链接)。
我认为@fred 的回答更正确。 IIUC 这个答案的问题在于,每次添加一行时,它都会不必要地复制整个 DataFrame。使用可以避免的 .loc 机制,特别是如果您小心的话。
但是如果你想使用 DataFrame.append(),你必须首先确保你的行数据也是一个 DataFrame,而不是一个列表。
DataFrame.append() 是 deprecated since version 1.4.0,以后只使用 pandas.concat() 就像 pandas.concat([DF1, DF2])
c
cs95

永远不要增长 DataFrame!

是的,人们已经解释过你不应该增长一个 DataFrame,你应该将你的数据附加到一个列表中,并在最后将它转换为一个 DataFrame。但是你明白为什么吗?

以下是最重要的原因,摘自我的帖子 here

追加到列表并一次性创建 DataFrame 总是更便宜/更快。列表占用的内存更少,并且是一种更轻便的数据结构,可以使用、追加和删除。 dtypes 会自动为您的数据推断。另一方面,创建一个空的 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 append 和 concat 本身并不是孤立的。当您在循环中迭代地调用它们时,问题就开始了——这会导致二次内存使用。 # 创建空 DataFrame 并在 some_function_that_yields_data() 中为 a, b, c 添加 df = pd.DataFrame(columns=['A', 'B', 'C']): df = df.append({'A': i, 'B': b, 'C': c}, ignore_index=True) # 这同样糟糕:# df = pd.concat( # [df, pd.Series({'A': i, 'B' : b, 'C': c})], #ignore_index=True) NaN 的空 DataFrame 永远不要创建 NaN 的 DataFrame,因为列是用 object 初始化的(慢的,不可矢量化的 dtype)。 # 创建 NaN 的 DataFrame 并覆盖值。 df = pd.DataFrame(columns=['A', 'B', 'C'], index=range(5)) for a, b, c in some_function_that_yields_data(): df.loc[len(df)] = [a,b,c]

证据就在布丁里

对这些方法进行计时是查看它们在内存和效用方面有多大差异的最快方法。

https://i.stack.imgur.com/sGIV6.png

Benchmarking code for reference.

像这样的帖子提醒我为什么我是这个社区的一员。人们明白教人们用正确代码得到正确答案的重要性,而不是用错误代码得到正确答案的重要性。现在您可能会争辩说,如果您只是向 DataFrame 添加一行,那么使用 locappend 不是问题。然而,人们通常希望这个问题不仅仅是添加一个 - 通常要求是使用来自函数的数据在循环内迭代地添加一行(见related question)。在这种情况下,重要的是要了解迭代增长 DataFrame 不是一个好主意。


很公平。如果您需要(或想要)一个数据框,是否有任何解决方案,但您的所有样本确实一个接一个地出现? (通常是在线学习或主动学习)
这不考虑在每个 append() 之后需要数据帧的情况。在这种情况下,无论如何都会复制数据框,因此 df.loc 方法更快
@DevAggarwal 不正确, loc 每次也会创建一个副本。请在我的答案中查看图表时间。 Append 和 loc_append 同样糟糕。我还分享了我的代码和流程,因此您可以自由地说服自己。
道歉应该更清楚。请从 for 循环内的中间列表创建数据框,这里 - gist.github.com/Coldsp33d/…
有没有人对@DevAggarwal 的建议进行基准测试?我经常遇到这种情况
F
FooBar

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

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
L
Lydia
mycolumns = ['A', 'B']
df = pd.DataFrame(columns=mycolumns)
rows = [[1,2],[3,4],[5,6]]
for row in rows:
    df.loc[len(df)] = row

这个!我已经搜索了很长时间,这是第一篇真正展示如何将特定值分配给行的帖子!额外的问题:列名/值对的语法是什么?我想它一定是使用 dict 的东西,但我似乎做错了。
这效率不高,因为它在扩展时实际上复制了整个 DataFrame。
考虑改用 len(df.index)
W
W.P. McNeill

您可以使用 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>)
有没有办法做到这一点?
@哈哈,不。请参阅 github.com/pandas-dev/pandas/issues/2801 - 基础数组无法扩展,因此必须复制它们。
我更喜欢这种方法,因为它非常类似于 SQL(在语义上不依赖于索引)并且我尽可能使用它。
P
Peter Mortensen

如需高效追加,请参阅 How to add an extra row to a pandas dataframeSetting With Enlargement

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

用户要求实施(添加新行)。在这里,我们看到如何在定义的索引中添加一行或添加一列。
与 dict 方法相比,任何关于它如何工作的基准
这效率不高,因为它实际上复制了整个 DataFrame。
P
Peter Mortensen

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

B
Brian Burns

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

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

P
Peter Mortensen

我想出了一个简单而好方法:

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

请注意评论中提到的性能警告。


请注意,这将在后台复制整个 DataFrame。底层数组无法扩展,因此必须复制它们。
P
Peter Mortensen

如果您总是想在最后添加一个新行,请使用以下命令:

df.loc[len(df)] = ['name5', 9, 0]

这假定数据帧的索引是编号的并且它是完全连续的。使用 df.reset_index() 可以解决此问题,但就目前而言,它实际上可能会覆盖现有行。
P
Peter Mortensen

这不是 OP 问题的答案,而是说明 ShikharDua's answer 的玩具示例,我发现它非常有用。

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

P
Peter Mortensen

您可以使用生成器对象来创建数据框,这将比列表更节省内存。

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

要将 raw 添加到现有 DataFrame 中,您可以使用 append 方法。

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

P
Peter Mortensen

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

P
Peter Mortensen

除了 ShikharDua's answer 中的字典列表之外,我们还可以将表表示为 列表字典,其中每个列表按行顺序存储一列,前提是我们事先知道列。 最后我们构建了一次 DataFrame。

对于 c 列和 n 行,这使用一个字典和 c 个列表,而不是一个列表和 n 个字典。 list-of-dictionaries 方法让每个字典存储所有键,并且需要为每一行创建一个新字典。这里我们只追加到列表,这是恒定的时间,理论上非常快。

# 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

P
Peter Mortensen

以下是在 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])

它可用于在空的或填充的 Pandas DataFrame 中插入/追加一行。


这是按降序添加索引
P
Peter Mortensen

如果要在末尾添加一行,请将其附加为列表:

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

q
qed

另一种方法(可能不是很好):

# 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

G
Giorgos Myrianthous

您只需要 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] 

P
Peter Mortensen
initial_data = {'lib': np.array([1,2,3,4]), 'qty1': [1,2,3,4], 'qty2': [1,2,3,4]}

df = pd.DataFrame(initial_data)

df

lib    qty1    qty2
0    1    1    1
1    2    2    2
2    3    3    3
3    4    4    4

val_1 = [10]
val_2 = [14]
val_3 = [20]

df.append(pd.DataFrame({'lib': val_1, 'qty1': val_2, 'qty2': val_3}))

lib    qty1    qty2
0    1    1    1
1    2    2    2
2    3    3    3
3    4    4    4
0    10    14    20

您可以使用 for 循环遍历值或添加值数组。

val_1 = [10, 11, 12, 13]
val_2 = [14, 15, 16, 17]
val_3 = [20, 21, 22, 43]

df.append(pd.DataFrame({'lib': val_1, 'qty1': val_2, 'qty2': val_3}))

lib    qty1    qty2
0    1    1    1
1    2    2    2
2    3    3    3
3    4    4    4
0    10    14    20
1    11    15    21
2    12    16    22
3    13    17    43

对第一部分的解释是有序的。为什么在讨论示例代码时没有“for”循环?你能说得更清楚一点吗?请通过 editing your answer 回复,而不是在评论中(没有“编辑:”、“更新:”或类似内容 - 答案应该看起来好像是今天写的)。
P
Peter Mortensen

您可以为此连接两个 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])

这就是我需要的
P
Peter Mortensen

让它变得简单。通过将列表作为输入,该列表将作为一行附加到数据框中:

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)

P
Peter Mortensen

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)

目前尚不清楚为什么前两行不是文字代码。简洁很好,但您可以elaborate in your answer,例如添加一些支持文本吗?但是没有“编辑:”、“更新:”或类似的 - 答案应该看起来好像是今天写的。
M
Mahdi

如果您有一个数据框 df 并希望将 list new_list 作为新行添加到 df,您只需执行以下操作:

df.loc[len(df)] = new_list

如果您想在数据框 df 下添加一个新的数据框 new_df,那么您可以使用:

df.append(new_df)

P
Peter Mortensen

我们经常看到构造 df.loc[subscript] = … 分配给一个 DataFrame 行。 Mikhail_Sam posted benchmarks 包含此构造以及使用 dict 并最终创建 DataFrame 的方法。他发现后者是迄今为止最快的。

但是如果我们用 df3.values[i] = … 替换他代码中的 df3.loc[i] = …(带有预分配的 DataFrame),结果会发生显着变化,因为该方法的执行类似于使用 dict 的方法。所以我们应该更多地考虑使用 df.values[subscript] = …。但是请注意,.values 采用从零开始的下标,这可能与 DataFrame.index 不同。


@baxx - 代码示例 位于 benchmarks 链接 (# .loc with prealloc),另一个示例位于问题 I have to compare data from each row of a Pandas DataFrame with data from the rest of the rows, is there a way to speed up the computation? 及其接受的答案中。
P
Peter Mortensen

在添加行之前,我们必须将数据框转换为字典。在那里,您可以将键视为数据框中的列,并且列的值再次存储在字典中,但每列的键是数据框中的索引号。

这个想法让我写了下面的代码。

df2 = df.to_dict()
values = ["s_101", "hyderabad", 10, 20, 16, 13, 15, 12, 12, 13, 25, 26, 25, 27, "good", "bad"] # This is the 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 the key of the sub dictionary
    i += 1

P
Peter Mortensen

如果 Dataframe 中的所有数据都具有相同的 dtype,则可以使用 NumPy 数组。您可以将行直接写入预定义的数组并在最后将其转换为数据帧。它似乎比转换字典列表还要快。

import pandas as pd
import numpy as np
from string import ascii_uppercase

startTime = time.perf_counter()
numcols, numrows = 5, 10000
npdf = np.ones((numrows, numcols))
for row in range(numrows):
    npdf[row, 0:] = np.random.randint(0, 100, (1, numcols))
df5 = pd.DataFrame(npdf, columns=list(ascii_uppercase[:numcols]))
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df5.shape)

关于“似乎更快”:你能量化一下(通过editing (changing) your answer)吗?我们在谈论什么顺序?快 10%?快 100%?快10倍?快 1,000,000 倍?在什么规模(它可以是二次/指数)?
P
Peter Mortensen

此代码片段使用字典列表来更新数据框。它增加了 ShikharDua'sMikhail_Sam's 的答案。

import pandas as pd
colour = ["red", "big", "tasty"]
fruits = ["apple", "banana", "cherry"]
dict1={}
feat_list=[]
for x in colour:
    for y in fruits:
#         print(x, y)
        dict1 = dict([('x',x),('y',y)])
#         print(f'dict 1 {dict1}')
        feat_list.append(dict1)
#         print(f'feat_list {feat_list}')
feat_df=pd.DataFrame(feat_list)
feat_df.to_csv('feat1.csv')