【问题标题】:Quickest way of mapping columns of an array to a new interval将数组的列映射到新间隔的最快方法
【发布时间】:2017-09-18 09:25:28
【问题描述】:

我有以下矩阵,它代表了一些点:

points = np.random.uniform(30, 50, size = (5,3))
# gives array([[ 45.98139489,  40.27871523,  41.91617071],
               [ 41.1404787 ,  34.56098247,  35.91171313],
               [ 34.46375465,  49.89872417,  39.04753134],
               [ 49.28112722,  32.01837698,  32.83394596],
               [ 48.96623168,  33.58271833,  33.54690091]])

现在每一列都是一个坐标。每列都有[30,50] 范围内的值。我想将每一列映射到不同的间隔。由于这个问题,我知道如何将点从一个区间映射到另一个区间: Algorithm to map an interval to a smaller interval

但我想做一些非常快的事情,并将每一列(可能)映射到不同的间隔。例如假设我们有

intervals = np.array([[0, 10], [3,7], [100,200]])

或者我们可以将它们分开在数组中作为xinterval = np.array([0,10]),没关系。

我的慢速尝试

我收集了intervals中的所有区间,然后通过循环在每一列上使用了转换

for col, interval in zip(range(points.shape[1]), intervals):
       points[:, col] = ((points[:,col]-min(points[:,col]))*(interval[1]-interval[0]) / (max(points[:,col])-min(points[:,col])) ) + interval[0]

为简单起见,我使用 min max 范围作为前一个区间,但我可以直接使用 30,50

for col, interval in zip(range(points.shape[1]), intervals):
       points[:, col] = ((points[:,col]-30)*(interval[1]-interval[0]) / (50-30) ) + interval[0]

有没有更快的方法,不使用循环?

【问题讨论】:

    标签: python arrays numpy matrix transform


    【解决方案1】:

    直截了当的广播

    这是使用broadcasting的一种矢量化方式-

    mins = points.min(0)
    a1 = (points - mins)* (intervals[:,1]-intervals[:,0])
    a2 = points.max(0) - mins
    out = a1/a2 + intervals[:,0]
    

    改进:较少广播

    仔细观察,我们正在几个地方表演broadacsting。尽管broadacsting 是一种非常有效的向量化方法,但它仍然有一些成本。我们可以改进它,通过重新安排周围的事情,以将broadcasting 步骤的数量减少到只有两个,而不是之前的四个。

    因此,修改后的将是 -

    mins = points.min(0)
    scale = (intervals[:,1]-intervals[:,0])/(points.max(0) - mins)
    offset = mins*scale - intervals[:,0]
    out = points *scale - offset
    

    我。之前的广播步骤:

    两个在:(points - mins)* (intervals[:,1]-intervals[:,0])

    两个在:a1/a2 + intervals[:,0]

    二。改进后的广播步骤:

    points *scale 一个,之后的减法一个。

    运行时测试

    方法-

    def app1(points, intervals):
        mins = points.min(0)
        a1 = (points - mins)* (intervals[:,1]-intervals[:,0])
        a2 = points.max(0) - mins
        out = a1/a2 + intervals[:,0]
        return out
    
    def app2(points, intervals):
        mins = points.min(0)
        scale = (intervals[:,1]-intervals[:,0])/(points.max(0) - mins)
        offset = mins*scale - intervals[:,0]
        out = points *scale - offset
        return out
    

    时间安排 -

    In [104]: points = np.array([[ 45.98139489,  40.27871523,  41.91617071],
         ...:                [ 41.1404787 ,  34.56098247,  35.91171313],
         ...:                [ 34.46375465,  49.89872417,  39.04753134],
         ...:                [ 49.28112722,  32.01837698,  32.83394596],
         ...:                [ 48.96623168,  33.58271833,  33.54690091]])
         ...: points = np.repeat(points, 100000,axis=0)
         ...: 
         ...: intervals = np.array([[0, 10], [3,7], [100,200]])
         ...: 
    
    In [105]: %timeit app1(points, intervals)
    10 loops, best of 3: 26.3 ms per loop
    
    In [106]: %timeit app2(points, intervals)
    100 loops, best of 3: 17.9 ms per loop
    

    【讨论】:

      猜你喜欢
      • 2019-08-08
      • 1970-01-01
      • 1970-01-01
      • 2014-11-29
      • 1970-01-01
      • 2017-04-23
      • 1970-01-01
      • 2020-08-06
      • 2018-09-16
      相关资源
      最近更新 更多