3

插入一维数组以使元素之间的最大差异最小化的简洁易读的方法是什么?

例如,如果我有数组 [4 9 13 25] 并且允许我再添加 1 个数字以最小化元素之间的最大差异,我将在 13 和 25 之间插入 19(最大差​​异现在是 6 而不是 12 )。

当然,一个好的 ole' for 循环可以完成它,但是对于后代来说,有没有比下面更简洁的方法?

# current array
nums = np.array([4.0, 9.0, 13.0, 25.0])
# size of new array
N=10

# recursively find max gap (difference) and fill it with a mid point    
for k in range(N-len(nums)):
    inds = range(len(nums))
    # get the maximum difference between two elements
    max_gap = np.argmax(np.diff(nums))
    # put a new number that's equidistant from the two element values
    new_num = np.interp(np.mean([inds[max_gap],inds[max_gap+1]]), inds, nums)
    nums = np.insert(nums, max_gap+1, new_num)
    print nums

此示例插入一维数组,填充最大差异的区域:

[  4.   9.  13.  19.  25.]
[  4.   9.  13.  16.  19.  25.]
[  4.   9.  13.  16.  19.  22.  25.]
[  4.    6.5   9.   13.   16.   19.   22.   25. ]
[  4.    6.5   9.   11.   13.   16.   19.   22.   25. ]
[  4.    6.5   9.   11.   13.   14.5  16.   19.   22.   25. ]

编辑 1: 正如评论所暗示的,在可读性、效率和准确性之间存在权衡。在这三个属性中,对我来说最重要的是可读性。我仍然对上述算法的任何和所有改进都给予 +1,因为这是一个普遍问题,任何改进这三个属性中的任何一个的答案都对某人有益,如果以后不是我的话。

4

3 回答 3

2

而且,如果您想要长数组的效率,即使代码不那么短,我建议:

nums = np.array([4., 9., 13., 25])
diffs = np.diff(nums)
N = 10

# Number of interpolation points proportional to length of gaps
new_points = diffs/sum(diffs) * (N-len(nums))
while sum(np.floor(new_points)) != N -len(nums): # from continuum to discrete 
    pos = np.argmax(new_points - np.floor(new_points))
    new_points[pos] = np.floor(new_points[pos] + 1)
new_points = np.floor(new_points)

# Now we interpolate by inserting linspace values starting from the end to 
# avoid the loop limits being spoiled when introducing values. 
for ii in range(len(new_points))[::-1]:
    #linspace includes borders
    introduce_these = np.linspace(nums[ii], nums[ii+1], new_points[ii] + 2)[1:-1]
    nums = np.insert(nums, ii+1, introduce_these)

这会产生:

In [205]: print nums
[4.   5.66666667   7.33333333   9.   11.   13.   16.   19.   22.   25. ]
于 2013-10-27T01:22:09.423 回答
1

如果数组很小并且可读性比效率更重要,我建议:

  nums = [4., 9., 13., 25]
  N = 10
  while len(nums) < N:
      pos = np.argmax(np.diff(nums))   # where maximum difference is
      nums.insert(pos+1, (nums[pos+1] + nums[pos]) / 2.)  #introduce value

当然,这会受到已经提到的问题的影响,即这可能不是以运行结束时点之间的最小差异进行插值的最有效方法。

于 2013-10-27T00:06:46.417 回答
1

您可以一次更新多个值。考虑以下:

for k in xrange(N/count):
    max_gaps = np.argsort(np.diff(nums))
    inds = np.sort(max_gaps[-count:])
    new_num = (nums[inds]+nums[inds+1])/2

    nums = np.insert(nums, inds+1, new_num)
    print nums

计数将是同时填补的空白数。

第一个例子 whencount=1N=6

[  4.   9.  13.  19.  25.]
[  4.   9.  13.  19.  22.  25.]
[  4.   9.  13.  16.  19.  22.  25.]
[  4.    6.5   9.   13.   16.   19.   22.   25. ]
[  4.    6.5   9.   11.   13.   16.   19.   22.   25. ]
[  4.    6.5   9.   11.   13.   16.   19.   22.   23.5  25. ]

此示例简化了线性插值和代码,但将采用最后一个最大的等效间隙而不是第一个。

第二个例子当count=2N=6

[  4.    6.5   9.   13.   19.   25. ]
[  4.    6.5   9.   13.   16.   19.   22.   25. ]
[  4.    6.5   9.   11.   13.   16.   19.   22.   23.5  25. ]

增加count会改变你的结果,但会帮助向量化代码。

于 2013-10-26T22:59:17.633 回答