内插一维数组的简洁易读方法是什么,以便最大限度地减少元素之间的最大差异?
例如,如果我有阵列[4 9 13 25]并且我被允许添加1个数字以最小化元素之间的最大差异,我将在13和25之间插入19(最大差异现在是6而不是12)。
当然,一个好的'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
此示例插入1D数组,填充区别最大的区域:
[ 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,因为它是一个普遍的问题,任何改进这三个属性中的任何一个的答案对于某些人来说都是有益的,如果不是我以后的话。
答案 0 :(得分: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. ]
答案 1 :(得分: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
计数将是同时填补的空白数量。
count=1
和N=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. ]
此示例简化了线性插值和代码,但 last 最大等效间隙不是第一个。
count=2
和N=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
会改变您的结果,但会有助于对代码进行矢量化。
答案 2 :(得分: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
当然,这会遇到已经提到的问题,这可能不是最有效的插值方式,在运行结束时点之间的最小差异。