【问题标题】:Python - easy way to "comparison" map one array to anotherPython - “比较”将一个数组映射到另一个数组的简单方法
【发布时间】:2017-11-16 14:22:49
【问题描述】:

我有一个数组a = [1, 2, 3, 4, 5, 6]b = [1, 3, 5],我想映射a,这样对于a 中位于b 中的元素之间的每个元素,它都会映射到@ 的索引987654326@ 这是包含a 的上限。不是最好的文字解释,但这里有一个例子

a = 1 -> 0 because a <= first element of b
a = 2 -> 1 because b[0] < 2 <= b[1] and b[1] = 3
a = 3 -> 1 
a = 4 -> 2 because b[1] < 4 <= b[2]

所以我想要的最终产品是f(a, b) = [0, 1, 1, 2, 2, 2]

我知道我可以循环并解决它,但我想知道在 pandas/numpy 中是否有一种聪明、快速(矢量化)的方法来做到这一点

【问题讨论】:

  • 这些数组总是有序的吗?
  • 是的,您可以假设它们是有序的。也可以假设 b 的每个元素都包含在 a 中(没有这个约束的更通用的解决方案会很棒,但我认为它更容易)

标签: python arrays pandas numpy


【解决方案1】:

使用python的bisect模块:

from bisect import bisect_left

a = [1, 2, 3, 4, 5, 6]
b = [1, 3, 5]

def f(_a, _b):
  return [bisect_left(_b, i) for i in _a]

print(f(a, b))

bisect — 数组二等分算法

此模块支持按排序顺序维护列表,而无需在每次插入后对列表进行排序。对于具有昂贵比较操作的长列表项目,这可能是对更常见方法的改进。该模块被称为 bisect,因为它使用基本的二分算法来完成它的工作。源代码作为算法的工作示例可能最有用(边界条件已经正确!)。

提供以下功能:

bisect.bisect_left(a, x, lo=0, hi=len(a))

a 中定位 x 的插入点以保持排序顺序。参数 lohi 可用于指定应考虑的列表子集;默认情况下使用整个列表。如果 x 已经存在于 a 中,则插入点将位于任何现有条目之前(左侧)。 假设 a 已经排序,返回值适合用作list.insert() 的第一个参数。

返回的插入点 i 将数组 a 分成两半,all(val &lt; x for val in a[lo:i]) 为左侧,all(val &gt;= x for val in a[i:hi]) 为右侧。

参考: https://docs.python.org/3/library/bisect.html

【讨论】:

    【解决方案2】:

    二分法更快:解决方案假定列表已排序

    a = [1, 2, 3, 4, 5, 6]
    b = [1, 3, 5]
    
    inds=[min(bisect_left(b,x),len(b)-1) for x in a]
    

    返回

    [0, 1, 1, 2, 2, 2]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-27
      • 2015-07-14
      • 2017-05-26
      • 1970-01-01
      • 2018-08-14
      • 2014-08-02
      • 1970-01-01
      相关资源
      最近更新 更多