【问题标题】:Pythonify Some Simple LoopsPythonify 一些简单的循环
【发布时间】:2014-03-17 18:39:16
【问题描述】:

目前,我正在开发一个巨大的测试套件,其中每个文件都经过了 387,072 次测试,我有 269 个文件需要测试。我用 Python 编写了所有的逻辑,它都做了它应该做的事情,但问题是它非常慢。

我想我已经确定了代码中的主要瓶颈。基本上,这些瓶颈似乎源于我使用 Python 为循环执行 C 样式索引。如果有人可以通过学习如何 Pythonify 来帮助我更好地使用 Python,我将不胜感激:

for i in range(len(mixed)):
    if (len(signal1Data.shape)>1):
        for row in range(signal1Data.shape[0]):
            if (i>=signal1Data[row,0] and i<=signal1Data[row,1]):
                signal1Indicator[i] = 1;
    else:
        if (i>=signal1Data[0] and i<=signal1Data[1]):
            signal1Indicator[i] = 1;

还有:

for i in range(1,len(changed),2):
    changed[i] -= 1;

signal1Data 的样子:

0 5000
5100 6778
8000 9246
...
etc

基本上,我试图混合两个信号,然后在索引位于 signal1Data 中的值之间时创建一个指标。如何通过 Pythonification 加快速度?

编辑:

mixed 保存了我正在混合的最终信号。它看起来像:

混合 = [-0.943263, -0.823721, -0.582382, -0.24921389, 0.000, ... 等]

同样,signal1 只是另一个信号,格式相同。

signal1Data 定义某些事件发生的位置。在我的示例中,我感兴趣的事件发生在 0 到 5000 之间,然后又发生在 5100 到 6778 之间,等等。这些数字是信号中发生事件的样本索引。当这个循环出现时,signal1Data 是一个 2D 整数数组(但有时它可以是 1D,因为只有 1 个事件并且我正在使用 numpy.loadtxt 加载它)。

【问题讨论】:

  • 我们提供的任何pythonic代码是否仍然需要遍历所有这些元素?如果是这样,我怀疑让它 pythonic 会提高它的速度。
  • 如果我们能更好地了解某些标识符的含义,将会有所帮助。 mixed 中有哪些数据? signal1Data 到底是什么?
  • 你为什么要用分号结束你的陈述?这是单调的,有点刺耳。 (在if 条件周围也加上不必要的括号。)
  • 如果您能向我们展示一些 mixedsignal1Data 的示例值以供测试,这也会很有帮助
  • @TheDude 这就是为什么我将其发布为评论而不是答案。答案应与问题严格相关,cmets 为了提供/询问有关问题的更多信息并指出问题的其他问题。在你的情况下,很明显你已经落入XY problem。如果你在 SO 上搜索一下,你会发现很多 cmets 包含笑话、正交信息等。

标签: python performance numpy


【解决方案1】:

对于第一个,您可以使用切片删除外循环和if

for start, stop in np.atleast_2d(signal1Data):
    signal1Indicator[start:stop+1] = 1

我不确定您是否可以将其完全矢量化。如果可以的话,它可能会更快,因为不太清晰和 Pythonic :)

第二个很简单,也可以切片:

changed[1::2] -= 1

【讨论】:

  • 这正是我想要的。谢谢你。它大大加快了速度!顺便说一句:对我来说,这更像是 Pythonic,因为它利用了 1. 切片和 2. 内置的 numpy。很好的答案。
【解决方案2】:

我不认为拥有更惯用的代码会使其更快,但您可以做以下几件事:

for 循环

for i in range(len(mixed)):

只有当你希望 i 是一个数字时才有意义,否则你可以使用

for item in some_list:

并且 item 会依次取 some_list 中存储的值。

要检查列表是否为空,您可以这样做

if some_list:

一个空列表将评估为假,一个非空列表将评估为真。不需要检查长度。

【讨论】:

    【解决方案3】:

    我不完全确定你想要做什么,但你可以做这样的事情来根据数组的索引创建一个掩码。

    data = np.arange(20).reshape(2,10) 
    i,j = np.meshgrid(*map(np.arange, data.shape), indexing='ij')
    mask = (j > 2) & (j < 6)
    #To get the values this mask defines, do this.
    data[mask].reshape(data.shape[0],-1) 
    

    【讨论】:

      【解决方案4】:

      目前我能想到的唯一改进是将if... else改为try.. except,如下所示:

      for i in range(len(mixed)):
          try:
              for row in range(signal1Data.shape[0]):
                  #Index Error exception is thrown below, if signal1Data is an array
                  if (i>=signal1Data[row,0] and i<=signal1Data[row,1]):
                      signal1Indicator[i] = 1
          except IndexError:
              if (i>=signal1Data[0] and i<=signal1Data[1]):
                  signal1Indicator[i] = 1
      

      我想到的其他小改进正在更改for i in range(len(mixed)) - 不确定mixed 是什么,但你在这里计算了两件事,两者都可能是不必要的。不是在你之后编辑

      您还计算range(signal1Data.shape[0]) 每个循环。我找不到任何关于 shape 时间复杂度的信息,但如果 mixed 足够大,在 for 循环之外创建 range(signal1Data.shape[0]) 可能会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-24
        • 1970-01-01
        • 2018-05-15
        • 2015-12-30
        相关资源
        最近更新 更多