Python Pandas 创建一长串要连接的数据框

Posted

技术标签:

【中文标题】Python Pandas 创建一长串要连接的数据框【英文标题】:Python Pandas creating a long list of dataframes to get concatenated 【发布时间】:2017-03-04 01:59:11 【问题描述】:

我正在做一个程序,在每次迭代时都会创建一些值(根本没有多少值:每次迭代只有约 50 个值,其中一些是 4-5 个短字符串,但大多数是 2-3 位整数)。大约有 3000 次迭代。

现在,我使用 pandas 数据框来存储给定迭代的约 50 个值,然后将 df 附加到数据框列表 (dflist) 中,一旦完成所有 3K 迭代,我将连接 3K 数据框(因为它们都有相同的列名)使用类似的东西:

df_final = pd.concat(dflist,axis=0)

是否有更好的方法来执行此过程,例如。只需使用 numpy 数组并沿轴 0 附加值,最后将完整的 numpy 数组转换为具有给定列名集的 Pandas 数据框?

我问是因为经过多次迭代(大约 3000 次迭代中的 200 次),代码速度大幅下降,系统内存使用率缓慢上升,据我所知,在迭代之间,我的所有值都被覆盖除了这个熊猫数据框列表之外的每次迭代,这似乎是每次迭代后唯一增长的东西。我正在使用 Python 2.7。当我在 Spyder GUI 中或仅从命令行运行我的脚本时,就会发生这种行为。

另一件事:尽管我实际保存的值相对较小(每次迭代大约 50 个值),但我提取这些汇总值所经过的数据非常大。所以原始的 csv 大约是 10 GB,有大约 2 亿行,我使用 pd.read_csv 对它进行分块,给定的块大小约为 50K 行。然后对于这 50K 行,我得到大约 50 个值。但我原以为每个块都是独立的,并且由于值被覆盖,内存使用量不应该像现在这样增长。

例子df:

    CHFAC   Bygoper  Change MinB  NumB  NumCombos   Total
0   abc3    574936022   +    1     1    1   11
1   abc3    574936022   -    1     0    0   0
2   abc3    574936022   +    2     1    1   11
3   abc3    574936022   -    2     0    0   0
4   abc3    574936022   +    5     1    1   11
5   abc3    574936022   -    5     0    0   0
6   abc3    574936022   +    10    1    1   11
7   abc3    574936022   -    10    0    0   0

【问题讨论】:

向我们展示你是 concat 的一到两个示例 df,根据你的帖子很难判断你有多少列、索引等。 【参考方案1】:

您可以发挥创造力并使用列表来存储数据,然后在循环结束时创建最终数据框。很难使用您的示例,因为我们对您的创建过程一无所知。我将给出一个通用答案,显示基于 10 次迭代的循环创建 2 列数据框,其中每次迭代都有不同的输出长度

import pandas as pd
from random import randint
col1_val, col2_val = [], []
for i in range(10):
    random_len = range(randint(0, 9))
    col1 = random_len
    col2 = random_len
    col1_val.extend(col1)
    col2_val.extend(col2)
pd.DataFrame('col1':col1_val, 'col2':col2_val)

输出[110]:

    col1  col2
0      0     0
1      1     1
2      2     2
3      3     3
4      4     4
5      0     0
6      1     1
7      2     2
8      3     3

现在让我们看看速度,使用列表方法:

import time
st = time.time()
col1_val, col2_val = [], []
for i in range(10000):
    random_len = range(randint(0, 9))
    col1 = random_len
    col2 = random_len
    col1_val.extend(col1)
    col2_val.extend(col2)
pd.DataFrame('col1':col1_val, 'col2':col2_val)
print time.time()-st
0.0499999523163

使用你的方法:

st = time.time()
dflist = []
for i in range(10000):
    random_len = range(randint(0, 9))
    col1 = random_len
    col2 = random_len
    dflist.append(pd.DataFrame('col1':col1, 'col2':col2))
pd.concat(dflist)
print time.time()-st
7.21199989319

所以对于 10000 次迭代,它会快大约 180 倍

【讨论】:

好的,这应该是对当前附加到数据帧列表的方法的改进。那么您提出的扩展列的方法的性能差异是什么: col1_val.extend(col1) 与一次将所有这些值附加到 numpy 数组?例如。 vals = np.vstack((vals,[1,2])) 用于 2 列示例? @sambajetson 扩展或附加一个 numpy 数组在内存方面不是很有效,我不建议这样做。你可以read this answer 举例说明为什么你不应该那样处理它

以上是关于Python Pandas 创建一长串要连接的数据框的主要内容,如果未能解决你的问题,请参考以下文章

最全的pandas面试基础100题目

在 pandas for python 中创建虚拟变量

尝试创建一种有效的方法来产生具有组合结果的交叉连接

pandas的基本用法

Python实现MySQL数据库连接---pymysql

Python学习笔记(四十三)virtualenv (创建一套“隔离”的Python运行环境)