2017-04-26 83 views
1

我遇到以下需要帮助的问题。 我有一个csv文件中的310条记录,其中包含一些关于错误的信息。 在另一个csv文件中,我有80万条包含有关行李统计的记录(可能导致错误的事件)。通过熊猫数据帧进行高效循环

与下面的脚本,我通过漏洞试图

  1. 循环,并选择一个。
  2. 循环通过统计记录和检查一些条件
  3. 如果有匹配,从错误记录统计 记录添加一列。
  4. 另存新文件

我的问题是,如果我能在使用numpy的或任何其他更有效的方式archieve这一点。 目前的方法是采取永远因为统计

任何帮助或提示在正确的方向的大小的运行将不胜感激。 感谢名单中adavance

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

可能会被很多不说'print'声明更快。 –

+0

@StefanPochmann注意到..我会摆脱那条线。 Thanx – Makten

+0

您可以在800k_records中搜索并隔离第三个文件中的所有错误(保留位置跟踪)。并在第三个文件中进行匹配?此外,并行执行多个搜索将有助于 – pwnsauce

回答

1

首先:你确定你的代码没有你想要它做什么?正如我所看到的那样,您一直在循​​环查看统计信息,因此如果您发现了与bug#1匹配的错误,您可以稍后用错误#310覆盖统计数据的相应附录。目前还不清楚你应该如何处理没有匹配错误事件的统计事件,但目前你在某些情况下为这些数据点存储了fault_created列。更不用说每次检查每个错误的每个事件所做的额外工作。

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

我不确定是否有向量化你的工作所有先进的方式,但因为你是在看310 VS 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') 

注意上面不会将无与伦比列的东西不平凡的,因为我不认为你有一个合理的在你的问题中的例子。无论你想设置什么样的默认值,都应该独立于bug列表,所以你应该在整个匹配考验之前设置这些值。

请注意,我为您的代码做了一些整容。您可以使用拆包分配来设置error中的所有这些值,并且删除这些变量的前缀可以使其更清晰。由于我们没有为统计数据框定义单独的变量,因此我们可以处理前缀。

正如您所看到的,您可以根据向量化逻辑索引操作来定义查找给定错误的所有匹配统计项的条件。生成的大熊猫Series调用inds对于统计数据框的每一行都有一个布尔值。这可以用于分配给名为'Fault''Created'的列的子集。请注意,您可以(也可能应该)按名称对列进行索引,至少我觉得这个更清晰和方便。

由于每个错误您codecreated是标量(可能是字符串),该矢量分配cols_stats['Fault'][inds] = codecols_stats['Created'][inds] = createdcols_stats每个索引项设置为这些标量。

我相信结果应该和以前一样,但要快得多,代价是增加内存使用。

可以在初始化时进一步简化,但如果没有MCVE,则很难说具体细节。至少,你可以用切片的符号:

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

但赔率是你只是忽略了几列,在这种情况下,它可能更清楚drop那些代替。例如,如果在dataset你有一个名为“垃圾”,你忽略了一个第七列,你可以设置

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

非常感谢您的详细解释。具有很大的意义。我的名声不够高,无法接受这个答案,但它确实符合我的意愿。竖起大拇指;) – Makten

+0

@Makten我很高兴它的作品。但是你不需要声望来接受答案:这是任何一个adker都能做的事情:)你只需要点击答案左边的刻度线。 –

+0

啊..不知道。感谢名单 – Makten