Python - 向数据帧添加行的有效方法

时间:2017-01-27 06:27:37

标签: python pandas numpy dataframe

从这个question和其他人看来,似乎不建议使用concatappend来构建pandas数据帧,因为它每次都会重新复制整个数据帧。

我的项目涉及每30秒检索一小部分数据。这可能会持续3天的周末,因此有人可以轻易地期望一次创建超过8000行。向此数据框添加行的最有效方法是什么?

7 个答案:

答案 0 :(得分:35)

我使用了这个答案的df.loc[i] = [new_data]建议,但我有> 500,000行,这非常慢。

虽然给出的答案对OP的问题有好处,但我发现它更有效率,在前面处理大量行(而不是OP描述的欺骗行为)时使用csvwriter来添加数据到内存中的CSV对象,然后最后使用pandas.read_csv(csv)生成所需的DataFrame输出。

from io import BytesIO
from csv import writer 
import pandas as pd

output = BytesIO()
csv_writer = writer(output)

for row in iterable_object:
    csv_writer.writerow(row)

output.seek(0) # we need to get back to the start of the BytesIO
df = pd.read_csv(output)
return df

这对于~500,000行来说快了1000倍,随着行数增加,速度提升只会变大(the df.loc[1] = [data]相对来说会慢得多)

希望这可以帮助那些在处理比OP更多行时需要效率的人。

答案 1 :(得分:17)

您可以使用loc在不存在的索引上就地向DataFrame添加行。来自Pandas documentation

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

In [120]: dfi.loc[3] = 5

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

正如预期的那样,使用loc要比append(大约14倍)快得多:

import pandas as pd
df = pd.DataFrame({"A": [1,2,3], "B": [1,2,3], "C": [1,2,3]})

%%timeit
df2 = pd.DataFrame({"A": [4], "B": [4], "C": [4]})
df.append(df2)

# 1000 loops, best of 3: 1.61 ms per loop

%%timeit
df.loc[3] = 4

# 10000 loops, best of 3: 113 µs per loop

答案 2 :(得分:2)

您需要将问题分为两部分:

  1. 有效地每30秒接收一次数据(收集数据)。
  2. 收集数据后处理数据。
  3. 如果您的数据很关键(也就是说,您不能丢失它) - 将其发送到队列,然后批量从队列中读取它。

    队列将提供可靠(保证)接受,并且您的数据不会丢失。

    您可以从队列中读取数据并将其转储到数据库中。

    现在,您的Python应用程序只是从数据库中读取数据,并以适合应用程序的任何时间间隔进行分析 - 也许您希望按小时平均值进行分析;在这种情况下,您将每小时运行一次脚本以从数据库中提取数据,并可能将结果写入另一个数据库/表/文件中。

    底线 - 分割收集和分析应用程序的部分。

答案 3 :(得分:1)

假设您的数据帧已按顺序编入索引,则您可以:

首先检查下一个索引值是什么以创建新行:

myindex = df.shape[0]+1 

然后使用'at'写入每个所需的列

df.at[myindex,'A']=val1
df.at[myindex,'B']=val2
df.at[myindex,'C']=val3

答案 4 :(得分:1)

汤姆·哈维的反应很好。但是,我想基于pandas.DataFrame.from_dict添加一个更简单的答案。

通过将一行中的数据添加到列表中,然后将此列表添加到字典中,然后可以使用pd.DataFrame.from_dict(dict)创建一个数据框而无需迭代。

如果字典的每个值都是一行。您可以只使用: pd.DataFrame.from_dict(dictionary,orient='index')

小例子:

# Dictionary containing the data
dic = {'row_1':['some','test','values',78,90],'row_2':['some','test','values',100,589]}

# Creation of the dataframe
df = pd.DataFrame.from_dict(dic,orient='index')
df
          0       1       2      3       4
row_1   some    test    values  78       90
row_2   some    test    values  100     589

答案 5 :(得分:0)

sundance 的回答在用法上可能是正确的,但基准测试是错误的。 正如 moobie 正确指出的那样,在此示例中已经存在索引3,这使访问方式比不存在索引时更快。看看这个:

%%timeit
test = pd.DataFrame({"A": [1,2,3], "B": [1,2,3], "C": [1,2,3]})
for i in range(0,1000):
    testrow = pd.DataFrame([0,0,0])
    pd.concat([test[:1], testrow, test[1:]])

每个循环2.15 s±88毫秒(平均±标准偏差,共7次运行,每个循环1次)

%%timeit
test = pd.DataFrame({"A": [1,2,3], "B": [1,2,3], "C": [1,2,3]})
for i in range(0,1000):
    test2 = pd.DataFrame({'A': 0, 'B': 0, 'C': 0}, index=[i+0.5])
    test.append(test2, ignore_index=False)
test.sort_index().reset_index(drop=True)

每循环972 ms±14.4 ms(平均±标准偏差,共运行7次,每个循环1次)

%%timeit
test = pd.DataFrame({"A": [1,2,3], "B": [1,2,3], "C": [1,2,3]})
for i in range(0,1000):
    test3 = [0,0,0]
    test.loc[i+0.5] = test3
test.reset_index(drop=True)

每个循环1.13 s±46毫秒(平均±标准偏差,共7次运行,每个循环1次)

当然,这纯粹是综合的,我承认并没有期望得到这些结果,但是似乎在不存在索引的情况下,.loc.append的表现非常相似。只是把它留在这里。

答案 6 :(得分:0)

我从SQL Server返回了70万行数据。 以上所有事情对我来说都花费了很长时间。 以下方法可以大大节省时间。

from collections import defaultdict
dict1 = defaultdict(list)

for row in results:

   dict1['column_name1'] = row['column_name1']


   dict1['column_name20'] = row['column_name20']

df = pd.DataFrame(dict1)

这就是我所需要的。