我正在寻找一种方法来加快我在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次迭代?
谢谢!
答案 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行)中的任何建议?
再次感谢!