【问题标题】:Create array of index values from list with another list python使用另一个列表python从列表创建索引值数组
【发布时间】:2019-03-03 02:31:33
【问题描述】:

我有一个值数组以及另一个我想为其创建索引的数组。 例如:

value_list = np.array([[2,2,3],[255,243,198],[2,2,3],[50,35,3]])
key_list = np.array([[2,2,3],[255,243,198],[50,35,3]])
MagicFunction(value_list,key_list)
#result = [[0,1,0,2]] which has the same length as value_list

我在研究后在网上看到的解决方案并不完全符合我的要求,我相信,任何帮助将不胜感激! 我有这个提供结果的蛮力代码,但我什至不想在我的实际数据大小上测试它

T = np.zeros((len(value_list)), dtype = np.uint32)
for i in range(len(value_list)):
    for j in range(len(key_list)):
        if sum(value_list[i] == key_list[j]) == 3:
            T[i] = j

【问题讨论】:

  • 与其做sum(value_list[i] == key_list[j]) == 3,不如做(value_list[i] == key_list[j]).all()。这两者都可以推广到任何大小,而不仅仅是 3,并且它更清楚代码的功能是什么。您也可以在T[i] = j 之后添加break 以节省一些时间。

标签: python image numpy indexing


【解决方案1】:

问题是如何让它不是非常低效。我看到了两种方法

  1. 使用字典以便快速查找。 numpy 数组是可变的,因此不可散列,因此您必须将它们转换为,例如,与字典一起使用的元组。

  2. 使用广播以矢量化方式检查 value_listkey_list 中的每个“键”。这至少会将 for 循环带出 Python,但您仍然需要将每个值与每个键进行比较。

我在这里也假设key_list 只有唯一的“键”。

第一种方法的方法如下:

value_list = np.array([[2,2,3],[255,243,198],[2,2,3],[50,35,3]])
key_list = np.array([[2,2,3],[255,243,198],[50,35,3]])

key_map = {tuple(key): i for i, key in enumerate(key_list)}
result = np.array([key_map[tuple(value)] for value in value_list])
result # array([0, 1, 0, 2])

这是第二个:

result = np.where((key_list[None] == value_list[:, None]).all(axis=-1))[1]
result # array([0, 1, 0, 2])

哪种方式更快可能取决于key_listvalue_list 的大小。我会为您安排典型大小的数组。

编辑 - 如 cmets 中所述,第二种解决方案似乎并不完全正确,但我不确定是什么导致它失败。考虑改用第一种解决方案。

【讨论】:

  • 谢谢你,你的第一个解决方案效果很好,它只有大约 4 秒,这对于我目前使用的数组大小来说是完全合理的:value_list.shape (1783296, 3), key_list.shape (59273, 3)。您的第二个解决方案出现“布尔”对象没有属性“全部”的错误。
  • @RobinWhite 如果这回答了您的问题,您可以通过单击答案左侧的复选标记来接受它,让其他人知道您的问题已得到解决。如果您可以使用我的第二个解决方案失败的小示例数组来编辑您的问题,我可以尝试看看那里发生了什么,但是当您需要进行大量比较时,另一个解决方案会更有效,所以如果可行,我们可以离开它。我将进行编辑,说明第二种解决方案并不总是有效。
  • 非常感谢您的评论,感谢您的澄清。我正在从一堆图像中获取数组。我刚刚在单个图像上再次运行了您的第二个代码并且它有效,所以我有点困惑为什么它在堆栈上给了我这个错误。无论如何,单张图像的时间大约是 4 秒,而您的第一个解决方案大约需要 0.05 秒 - 所以我会坚持使用那个。
  • 我再次尝试了这个,你的第二个解决方案正在工作,我的代码中一定有一些东西被清理了。解决方案 1 的时间是 4s,解决方案 2 的时间是 43s。再次感谢您,非常感谢您的帮助
【解决方案2】:

假设:

  1. value_list 的每个元素将出现在key_list(在某个位置或其他位置)
  2. 我们对key_list 中的索引感兴趣,只有第一个匹配

解决方案:

从这两个数组中,我们创建了三元组的视图。然后我们在两个正交方向广播这两个视图,然后检查广播数组上的元素相等性。

import numpy as np

value_list = np.array([[2,2,3],[255,243,198],[2,2,3],[50,35,3]], dtype='uint8')
key_list   = np.array([[2,2,3],[255,243,198],[50,35,3]], dtype='uint8')

# Define a new dtype, describing a "structure" of 3 uint8's (since
# your original dtype is uint8). To the fields of this structure,
# give some arbitrary names 'first', 'sec', and 'third'
dt = np.dtype([('first', np.uint8, 1),('sec', np.uint8, 1),('third', np.uint8, 1)])

# Now view the arrays as 1-d arrays of 3-tuples, using the dt
v_value_list = value_list.view(dtype=dt).reshape(value_list.shape[0])
v_key_list   = key_list.view(dtype=dt).reshape(key_list.shape[0])

result = np.argmax(v_key_list[:,None] == v_value_list[None,:], axis=0)
print (result)

输出:

[0, 1, 0, 2]

注意事项:

    1234563在第一次成功匹配时巧妙地停止。获得的任何优势将取决于key_list 的实际大小,以及成功匹配发生在key_list 中的位置。随着key_list 大小的增长,numpy 的优势可能会受到一些侵蚀,特别是如果成功的匹配主要发生在key_list 的早期部分。
  1. 我们正在创建的视图实际上是 numpy 结构化数组,其中视图的每个元素是两个 int 的结构。一个我尚未探索的有趣问题是,当 numpy 将一个结构与另一个结构进行比较时,它是否会对结构中的每个字段进行比较,或者是否会在第一个失败的字段中短路字段比较结构?任何这样的短路都可能意味着这种结构化阵列解决方案的额外优势。

【讨论】:

  • 谢谢你的建议,当我在我的实际数据数组上尝试这个时,我收到一个错误:'当更改为更大的 dtype 时,它​​的大小必须是总大小的除数(以字节为单位)数组的最后一个轴。我正在使用 numpy 版本 1.15.4。我不太确定这是在告诉我什么。我的数组是 value_list.shape (1783296, 3), key_list.shape (59273, 3)
  • 你能告诉我你的value_list.dtypekey_list.dtype吗?
  • 它们都是uint8
  • @RobinWhite:我已经相应地更新了我的答案,以避免你提到的错误(只是“解决方案”标题下的部分。我已经测试了这个错误(在第一次模拟错误之后) . 应该可以。请告诉我进展如何。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-30
相关资源
最近更新 更多