【问题标题】:IndexError: list index out of range when creating 2D arrayIndexError:创建二维数组时列表索引超出范围
【发布时间】:2020-08-09 17:45:53
【问题描述】:

我试图获得一个大小为 235x20 的二维数组,这样对于 235 个 ROI 中的每一个,我根据存储在 find_bootstrap_indices 中的索引提取 20 个元素并将它们保存在 extract_bootstrap_timepoint 中。现在,我想将每个 ROI 的值及其对应的 20 个元素存储在一个数组中。我试图通过这条线new[roi][timepoint] = extract_bootstrap[timepoint] 来做到这一点,但我遇到了索引超出范围错误。任何有关如何解决此问题的帮助将不胜感激。谢谢。

new = []
for roi in range(0, rsfMRI_timeseries_2d.shape[0]):
        extract_bootstrap_timepoint = np.take(rsfMRI_timeseries_2d[roi, :], find_bootstrap_indices)
        for timepoint in range(0, len(extract_bootstrap_timepoint)):
            new[roi][timepoint] = extract_bootstrap_timepoint[timepoint]

【问题讨论】:

  • 您需要在分配给它之前创建new[roi] 列表。喜欢new[roi] = []

标签: python numpy loops indexing


【解决方案1】:

其他答案已经涵盖了如何修复错误,但不要提到有更简单的方法来完成整个事情。

总的来说,我可以想到人们使用 Numpy 的几个不同原因:

  1. Numpy 数组可以比 Python 列表更快,如果每个数组有大量数据,则不需要在 Numpy 数组和 Python 列表之间来回转换,而是使用隐式操作整个数组的 Numpy 操作,而不是显式循环单个元素
  2. 使用 Numpy 数组的代码可以更简洁,因为您通常可以使用例如。用单个 Numpy 操作替换多个嵌套循环
  3. 您只想使用 Numpy 中已经提供的一些功能

您错过了第 1 点和第 2 点;您正在使用 Numpy,但您并没有充分利用它,因此您的代码没有达到应有的速度和简洁性。

首先,一些非 Numpy 的建议:

  • 除非您使用range() 的三参数形式,否则如果起始位置为 0,则可以省略起始位置 - 即。 range(N)range(0, N) 做同样的事情
  • 如果您正在迭代列表/数组的所有索引,并且仅将它们用于直接索引所述数组(即不用于例如计算),您应该直接迭代值而不是 - IE。而不是for i in range(len(items)): item = items[i],你应该做for item in items:。如果你还需要索引,可以说for i, item in enumerate(items):
  • 在您的内部循环中,您只是一个接一个地复制项目 - 如果您不需要单独对项目执行任何操作,只需一次性完成:(我将缩短 extract_bootstrap_timepointebt)
    • 如果类型没问题,并且不需要副本,只需像new[roi] = ebt 一样分配它
    • 如果它是一个数组(如这里)并且您想要一个列表,只需先将其转换为 new[roi] = list(ebt)new[roi] = ebt.tolist()(后者仅适用于数组)
    • 如果它已经是一个列表,并且您需要一个副本,只需复制一个,例如 new[roi] = ebt.copy()new[roi] = ebt[:](后者不适用于数组)
    • 如果您已经有一个更长的列表,并且您只想覆盖尽可能多的项目,您可以使用像 new[roi][:len(ebt)] = ebt 这样的切片分配

因此,应用该建议,您的代码将简化为:

new = []
for row in rsfMRI_timeseries_2d:
        new.append(np.take(row, find_bootstrap_indices).tolist())

现在,进入更具体的 Numpy 建议:

  • np.take(arr, indices) 做精美的索引;具体来说,如果arr 是一个Numpy 数组,indices 是一个Python 列表,则它等价于arr[indices]
  • 正常的 Numpy 索引返回相同共享数据的新视图,但是当您使用花哨的索引时,您会获得数据的副本(因此即使您需要副本,在这种情况下也无需显式复制)李>

由于您只是对rsfMRI_timeseries_2d 中的每一行执行相同的操作,并且np.take 调用也可以用索引替换,因此整个循环可以替换为:

new = rsfMRI_timeseries_2d[:,find_bootstrap_indices].tolist()

虽然,由于您使用的是 Numpy,您可能希望使用 Numpy 数组而不是嵌套的 Python 列表 - 如果是这样,整个事情就变得简单了:

new = rsfMRI_timeseries_2d[:,find_bootstrap_indices]

【讨论】:

  • 太棒了,非常感谢您的精彩解释并展示了解决我问题的优化方法。
【解决方案2】:

我认为你需要这样做:

new = []
for roi in range(0, rsfMRI_timeseries_2d.shape[0]):
    extract_bootstrap_timepoint = np.take(rsfMRI_timeseries_2d[roi, :], find_bootstrap_indices)
    new[roi] = extract_bootstrap_timepoint[:] # Copy data.

【讨论】:

  • Numpy 中的普通索引总是返回一个视图,所以arr[:] 不返回一个副本;花式索引(np.take() 确实如此)总是返回一个副本,所以你根本不需要一个显式的副本。 (虽然np.take() 返回一个数组,所以如果你想要一个列表而不是数组列表,你需要做一个转换——这无论如何都会产生一个新的列表)
【解决方案3】:

这会创建元素列表并操作值

new = [0]*rsfMRI_timeseries_2d.shape[0]
for roi in range(0, rsfMRI_timeseries_2d.shape[0]):
    xtract_bootstrap_timepoint = np.take(rsfMRI_timeseries_2d[roi, :], find_bootstrap_indices)
    new[roi]=[0]*len(extract_bootstrap_timepoint)
    for timepoint in range(0, len(extract_bootstrap_timepoint)):
        new[roi][timepoint] = extract_bootstrap_timepoint[timepoint]

另一种方法是附加值。

new = []
for roi in range(0, rsfMRI_timeseries_2d.shape[0]):
    xtract_bootstrap_timepoint = np.take(rsfMRI_timeseries_2d[roi, :], find_bootstrap_indices)
    l=list()
    for timepoint in range(0, len(extract_bootstrap_timepoint)):
        l.append(extract_bootstrap_timepoint[timepoint])
    new.append(l)

【讨论】:

  • 您好,感谢您的解决方案。它在一定程度上起作用。如果我使用你的第一个解决方案,那么 new 的长度是 235。我可以知道如何修改它,使得 new 是 235x20,它代表时间点的 roi。谢谢。
  • new[roi]=[0]*len(extract_bootstrap_timepoint) 此行为每个 new[i] 创建 20 个元素
  • 太好了,我还有最后一个问题。现在我有了大小为 235x20 的新数组。我可以知道我是否希望对 N 个主题重复该操作,那么如何将其附加到 for 循环之外。谢谢大家的帮助。
  • new=[[0]*235]*20.这将创建二维数组我希望你问这个
  • 本质上,我希望使用每个主题的 numpy.corrcoef 函数计算 235x20 的数组 new 的相关矩阵。如果我想这样做,每个主题的 numpy.corrcoef(new) 是否有意义?校正矩阵需要用 roi x 时间点来完成。谢谢。
【解决方案4】:

您需要在分配给它之前创建 new[roi][] 即:

new = []
for roi in range(0, rsfMRI_timeseries_2d.shape[0]):
        extract_bootstrap_timepoint = np.take(rsfMRI_timeseries_2d[roi, :], find_bootstrap_indices)
        new[roi] = []
        for timepoint in range(0, len(extract_bootstrap_timepoint)):
            new[roi][timepoint] = extract_bootstrap_timepoint[timepoint]

【讨论】:

  • 那行不通:你创建了一个空列表,但你只能引用现有的索引,否则你会得到 IndexError。您要么必须使用list.append(),要么从一开始就使列表足够大。
猜你喜欢
  • 1970-01-01
  • 2015-10-20
  • 1970-01-01
  • 1970-01-01
  • 2020-04-26
  • 1970-01-01
  • 1970-01-01
  • 2011-10-31
  • 2015-06-26
相关资源
最近更新 更多