有关优化pandas脚本删除循环(问题,压缩,...)的问题

时间:2019-02-11 12:42:19

标签: python pandas dataframe

我正在寻找一种方法来加快我在pandas数据框中的脚本。

要了解这种情况,我将举例说明脚本中涉及的两个数据集。

首先,我们有“ entrydata”,这是我们购买的商品的列表。上面的表格中有一个名为“日期”的列,一个名为“ id”的列和一个名为“值”的列:

<table>
  <tr>
    <th>Date</th>
    <th>Id</th> 
    <th>Value</th>
  </tr>
  <tr>
    <td>01/01/2017</td>
    <td>111</td> 
    <td>58.4</td>
  </tr>
  <tr>
    <td>01/01/2017</td>
    <td>222</td> 
    <td>120.7</td>
  </tr>
  <tr>
    <td>02/18/2017</td>
    <td>111</td> 
    <td>59.3</td>
  </tr>
  <tr>
    <td>02/18/2017</td>
    <td>222</td> 
    <td>130.8</td>
  </tr>
  <tr>
    <td>04/13/2017</td>
    <td>111</td> 
    <td>59.3</td>
  </tr>
  <tr>
    <td>04/13/2017</td>
    <td>222</td> 
    <td>130.8</td>
  </tr>
</table>

我们拥有的其他数据是“ outdata”,即我们出售的商品的列表,我们有一个名为“ date”的列,一个名为“ id”的列和一个名为“ value”的列,如上表所示:

<table>
  <tr>
    <th>Date</th>
    <th>Id</th> 
    <th>Value</th>
  </tr>
  <tr>
    <td>01/03/2017</td>
    <td>111</td> 
    <td>60</td>
  </tr>
  <tr>
    <td>01/03/2017</td>
    <td>111</td> 
    <td>60</td>
  </tr>
  <tr>
    <td>01/03/2017</td>
    <td>111</td> 
    <td>60</td>
  </tr>
  <tr>
    <td>01/03/2017</td>
    <td>222</td> 
    <td>122</td>
  </tr>
  <tr>
    <td>01/03/2017</td>
    <td>222</td> 
    <td>122</td>
  </tr>
  <tr>
    <td>02/25/2017</td>
    <td>222</td> 
    <td>122</td>
  </tr>
  <tr>
    <td>02/25/2017</td>
    <td>111</td> 
    <td>70</td>
  </tr>
  <tr>
    <td>02/25/2017</td>
    <td>222</td> 
    <td>135</td>
  </tr>
</table>

对于这些数据集,我编写了一个脚本,该脚本使用了for循环,如上面的代码:

for row in tqdm(zip(dbOut["Date"],dbOut["Id"],dbOut["Value"])):
    dateOut = row[0]
    idOut = row[1]
    valueOut = row[2]

    #get all entry rows that have idOut id
    dbSample = dbEntry.loc[dbEntry["Id"] == idOut]

    #now do the mean of the column Value
    result = dbSample["Value"].mean()

    #append to an array created before the loop
    valuefinal.append(result)

#out of loop we put it in the outdata dataFrame in a new column
dbOut["FinalValue"] = valuefinal

基本上,这些是脚本执行的操作。进出帧中有更多列,但是通过这些示例,我认为我已经恢复了正在发生的事情。

这些代码在结果方面效果很好,但是我想加快速度。首先,代码是使用循环使用循环编写的。在寻找一种加快速度的方法时,我发现迭代是一个不好的选择。所以我改成了itertuples,而不是zip函数。

所有结果都可以使用,但是迭代时间并没有太大变化。我说的是每秒约300次迭代。

然后我使用矢量化对部分代码进行了更改,并且根据录入数据,我将速度提高到了600至1200次/秒。

部分代码可以被矢量化,而另一部分则不能!可矢量化的部分是使用另外两列进行简单减法的部分。

使用具有特定ID的缩小数据帧的部分我无法矢量化,因为它显示了以下错误:

  

ValueError:只能比较标记相同的Series对象

我试图向量化的代码简单地从循环中删除,并进行了所需的更改。这是循环内的原始代码:

result = dbSample["Value"].mean

这是我尝试矢量化删除循环的代码:

dbOut["FinalValue"] = dbEntry.loc[dbEntry["Id"] == dbOut["Id"]]["Value"].mean()

最后,是问题。我可以使用数据帧的特定部分(entryData)进行此类矢量化吗?有什么建议可以使代码运行更快?像是每秒3000次迭代?

谢谢!

1 个答案:

答案 0 :(得分:0)

我实现了apply函数,该函数只返回一个值就可以很好地工作,当我使用所有需要的代码时,都会收到错误消息。

因此,在这里考虑,在zip循环中运行之前,我减少了dbOut。我没有删除dbOut的75000行,而是删除了重复项,只保留了ID列的每个1,并将其保存在dbOut2中,我将其保存在zip循环中。效率是,现在我只需要运行5000行,就可以使事情变得更快!

现在,我尝试将信息从dbOut2传递到de dbOut。我使用np.where,这是一种非常快速的方法:

dbOut["FinalValue"] = np.where(dbOut("ID") == dbOut2("ID"), dbOut2("Value"),0)

该行应该起作用,但我没有成功。关于如何正确地将dbOut2(5000行)中的信息放入dbOut(75000行)中的任何建议?

再次感谢!