python - 通过 pandas 数据框进行有效循环

标签 python performance pandas numpy vectorization

我有以下问题需要帮助。 我的 csv 文件中有 310 条记录,其中包含一些有关错误的信息。 在另一个 csv 文件中,我有 80 万条记录,其中包含有关袋子的统计信息(可能导致错误的事件)。

通过下面的脚本,我试图

  1. 循环检查错误并选择一个。
  2. 循环查看统计记录并检查一些条件
  3. 如果有匹配,则将 bug 记录中的一列添加到统计信息中 记录。
  4. 保存新文件

我的问题是我是否可以使用 numpy 或其他任何东西以更有效的方式实现这一点。 由于统计数据的大小,当前方法需要永远运行

任何正确方向的帮助或提示将不胜感激。 提前致谢

dataset = pd.read_csv('310_records.csv')
dataset1 = pd.read_csv('800K_records.csv')
cols_error = dataset.iloc[:, [0, 1, 2, 3, 4, 5, 6]]
cols_stats = dataset1.iloc[:, [1, 2, 3, 4, 5, 6, 7, 8, 9]]
cols_stats['Fault'] = ''
cols_stats['Created'] = ''

for i, error in cols_error.iterrows():    
    fault_created = error [0]
    fault_ucs = error [1]
    fault_dn = error [2]
    fault_epoch_end = error [3]
    fault_epoch_begin = error [4]
    fault_code = error [6]    

    for index, stats in cols_stats.iterrows():
        stats_epoch = stats[0]
        stats_ucs = stats[5]        
        stats_dn = stats[7]
        print("error:", i, " Stats:", index)        

        if(stats_epoch >= fault_epoch_begin and stats_epoch <= fault_epoch_end):
            if(stats_dn == fault_dn):
                if(stats_ucs == fault_ucs):
                    cols_stats.iloc[index, 9] = fault_code
                    cols_stats.iloc[index, 10] = fault_created

        else:
            cols_stats.iloc[index, 9] = 0
            cols_stats.iloc[index, 10] = fault_created

cols_stats.to_csv('datasets/dim_stats_error.csv', sep=',', encoding='utf-8')

最佳答案

首先:您确定您的代码能够实现您想要的功能吗?在我看来,您不断循环统计数据,因此,如果您发现与 bug #1 匹配的 bug,则稍后可以用 bug #310 覆盖统计数据的相应附录。目前尚不清楚您应该如何处理没有匹配错误事件的统计事件,但目前您正在为这些数据点存储 fault_created 列,这在某种程度上是任意的。更不用说每次检查每个事件以查找每个错误时所做的额外工作。

速度缓慢的原因是您根本没有利用 pandas 的功能。在 numpy 和 pandas 中,部分性能来自内存管理,其余部分来自矢量化。通过将大部分工作从 native Python 循环推送到矢量化函数(运行编译代码),您将开始看到速度的巨大提升。

我不确定是否有一种先进的方法来矢量化您的所有工作,但由于您正在查看 310 与 800k 项,因此对错误和错误进行循环似乎是完全合理的向量化内循环。关键是逻辑索引,使用它您可以一次寻址所有 800k 项:

for i, error in cols_error.iterrows():
    created, ucs, dn, epoch_end, epoch_begin, _, code = error

    inds = ( (epoch_begin <= cols_stats['epoch']) &
             (cols_stats['epoch'] <= epoch_end) &
             (cols_stats['dn'] == dn) &
             (cols_stats['ucs'] == ucs) )
    cols_stats['Fault'][inds] = code
    cols_stats['Created'][inds] = created

cols_stats.to_csv('datasets/dim_stats_error.csv', sep=',', encoding='utf-8')

请注意,上面的内容不会将不匹配的列设置为不重要的内容,因为我认为您的问题中没有合理的示例。无论您想要设置什么默认值都应该独立于错误列表,因此您应该在整个匹配考验之前设置这些值。

请注意,我对您的代码进行了一些修改。您可以使用解包赋值来设置 error 中的所有这些值,并删除这些变量的前缀使这一点更加清晰。我们可以处理前缀,因为我们没有为统计数据帧定义单独的变量。

正如您所看到的,查找给定错误的所有匹配统计项的条件可以根据矢量化逻辑索引操作来定义。生成的名为 inds 的 pandas Series 统计数据帧的每一行都有一个 bool 值。这可用于分配名为 'Fault''Created' 的列子集。请注意,您可以(并且可能应该)按名称索引列,至少我发现这更加更加清晰和方便。

由于对于每个错误,您的代码创建的都是标量(可能是字符串),因此矢量化赋值cols_stats['Fault'][inds] = codecols_stats['Created'][inds] = createdcols_stats 的每个索引项设置为这些标量。

我相信结果应该与以前相同,但速度更快,但代价是增加了内存使用。

可以在初始化中进行进一步的简化,但如果没有 MCVE,就很难说具体细节。至少你可以使用切片表示法:

cols_error = dataset.iloc[:, :7]
cols_stats = dataset1.iloc[:, 1:10]

但很可能您只是忽略了几列,在这种情况下,删除这些列可能会更清楚。例如,如果在数据集中中,您有一个名为“垃圾”的第七列被忽略,则只需设置

cols_error = dataset.drop('junk', axis=1)

关于python - 通过 pandas 数据框进行有效循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43632925/

相关文章:

python - 在 Pandas 数据框中显示对图

python - 根据现有列下一行的元素创建新列

python / Pandas : Find matching values from two dataframes and return third value

javascript - 长脚本的速度问题?

jquery - 我应该为 jQuery slider 使用 Sprite 吗?

mysql - 查询极慢

python - t检验在 Pandas 中

python - 如何找到重叠的intervalIndex pandas

python - SlugRelatedField 查询集

python - 关于python unicode的困惑