【问题标题】:Extracting values from indices without using loops从索引中提取值而不使用循环
【发布时间】:2015-07-22 16:02:55
【问题描述】:

所以我有一个包含数据的矩阵和一个包含我应该从矩阵中提取哪些数据的信息的向量。真正的矩阵要长得多,但下面是一个简短的版本,只是为了说明我的意思。

Data matrix = array([[1 2 3],[0 3 5],[1 4 4]]) 
Info vector = array([[1], [0], [2]])
Answer matrix = array([[2 (the second element)], [0(the first element)], 4(the third element)]])

简单的for循环:

length_data = data.shapes[0]
for i in xrange(length_data)
    answer[i] = data[info[i],i]

我知道如何使用简单的 for 循环来完成此操作,但如何使用矢量化来完成此操作,而不使用任何循环?

谢谢!

对问题的轻微补充:如果我希望答案如下所示怎么办

Answer matrix = array([[0 2 0], [0 0 0], [0 0 4]])

【问题讨论】:

  • 您的矩阵实际上是什么样的?它是自定义数据结构,还是只是列表列表/二维数组?
  • 如果它是一个列表,你可以这样做list.indexof(item)
  • 您确定您的语言正确吗? [1 2 3; 0 3 5; 1 4 4] 应该是什么?还是[1; 0; 2]
  • @mystery578.你需要添加你的 simple for 循环 因为你的输入数据看起来不像 python 但如果它是你听起来像你有 numpy 数组这是一个与常规 python 列表有很大不同
  • @mystery578,你有 numpy 数组,你应该用 numpy 标记问题,因为这里的所有答案都意味着你不再有 numpy 数组。更糟糕的是,它们会导致错误,__getitem__ -> descriptor '__getitem__' requires a 'list' object but received a 'numpy.ndarray'

标签: python numpy matrix vectorization


【解决方案1】:
>>> data = [[1, 2, 3], [0, 3, 5], [1, 4, 4]]
>>> info = [1, 0, 2]
>>> map(list.__getitem__, data, info)
[2, 0, 4]

【讨论】:

  • 为什么这被否决了?这是 100% 直截了当的答案,并且正如所证明的那样有效。
  • 从技术上讲,您最终会得到一个 map 对象,但如果您将其包装在 list() 中,它会提供一个带有所需输出的 ​​list。我不知道为什么这被否决了(忘记list() 电话不是充分的理由),但它有效并且非常整洁。
  • 不,我没有忘记list。我只是使用了 Python 2,其中map 确实返回了一个列表。我有时这样做是为了更清楚地展示实际的解决方案。
  • @StefanPochmann +1 为聪明的答案。我选择了lambdazip,但这要好得多。
  • @TigerhawkT3 你的意思是这个问题中的mystery578
【解决方案2】:

假设你的数据更有可能是numpy数组或者你安装了numpy,那么可以使用np.choose来实现:

In [3]: import numpy as np

In [4]: matrix = np.array([[1, 2, 3],[0, 3, 5],[1, 4, 4]])

In [5]: vector = np.array([[1], [0], [2]])

In [6]: np.choose(vector.flat, matrix.T)
Out[6]: array([2, 0, 4])

choose(a, 选择, out=None, mode='raise') 从一个索引数组和一组可供选择的数组构造一个数组。

使用vector.flat获取[1, 0, 2]的迭代器; matrix.T 获取当前matrix 的转置视图,np.choose 将使用vector 作为索引数组。

虽然使用choose 仍然会遍历vector 数组。

【讨论】:

  • 教授可能期待像这样一个numpy 导向的答案。
  • @TigerhawkT3,不幸的是,每个人都用直接的 Python 提供了很好的答案,直到最后我们都知道它是numpy。但无论如何都要欢呼:-)
  • 我不知道它是numpy,因为我从未使用过那个库。 :(
  • @TigerhawkT3,很可能开始入侵numpy,我也不是专家,但它非常强大且方便处理大量数字数据/数组/矩阵等。请注意询问您的域是什么,网络开发人员?
  • 我在从事技术写作。
【解决方案3】:

Numpy 允许您使用列表或数组进行索引,因此您只需使用 data[i, info] 其中i 是循环中的整个范围,而不仅仅是一个元素,info 是一维数组。

import numpy as np
data = np.array([[1, 2, 3], [0, 3, 5], [1, 4, 4]])
info = np.array([1, 0, 2])

i = np.arange(data.shape[0])
print(data[i, info])
# array([2, 0, 4])

很难从您的问题中看出,因为您实际上并没有发布工作代码,但看起来您的信息数组可能具有形状 (3, 1) 而不是 (3,)。在这种情况下,您只需要添加一个ravel

print(data[i, info.ravel()])
# array([2, 0, 4])

【讨论】:

    【解决方案4】:

    您需要将两个列表一起zip 像这样才能将第一个列表索引到另一个列表。

    answer = map(lambda x: x[0][x[1]], zip(data, info)) # [2, 0, 4]
    

    【讨论】:

    • data = [[1, 2, 3], [0, 3, 5], [1, 4, 4]]info = [1, 0, 2]
    • 你原来的循环不会比map(lambda...) 更快(更不用说更清晰)吗?老实说,我不确定我们为什么要在这里避免循环,而且我不清楚这个问题的“矢量化”会带来什么。
    • @TigerhawkT3 可能,但他说没有 for 循环。随便。
    • 是的,用 zip 功能解决了。谢谢!!!帮我学习了python中的一个新函数!
    • 随时。希望您能全面了解 Python 并享受它。
    【解决方案5】:

    没有循环?好的,没有循环。

    >>> m = [[1,2,3], [0,3,5], [1,4,4]]
    >>> v = [1,0,2]
    >>> def match(a, b):
    ...     return match_core([], iter(a), iter(b))
    ...
    >>> def match_core(l, a, b):
    ...     l.append(next(a)[next(b)])
    ...     try:
    ...         return match_core(l, a, b)
    ...     except StopIteration:
    ...         return l
    ...
    >>> match(m, v)
    [2, 0, 4]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-04
      • 1970-01-01
      • 2021-09-13
      • 2012-02-18
      • 2014-08-06
      • 2012-10-04
      • 1970-01-01
      • 2023-01-09
      相关资源
      最近更新 更多