我是一个完整的新手(甚至不是计算机科学家),但自从我开始学习Python&编程一般我想解决这个问题,看看这种事情有多难用编程来解决。 我也不知道从数学的角度来看这有多难以回答,是否容易进行几行代码还是需要做一些优化工作?
假设我有一组35'值'从1到200.
我想将它们分为5组('bins'),但我希望每个组(bin)的相同数量的'值'。所以图表将像5个相同高度的栏。所以不确定它仍然被称为直方图。无论如何,唯一的问题是如何计算(优化?)那些间隔/转换点。 / bin宽度。是否很难编码或根本不编码?
我只是指出,如果只有2个组(分档),“转换点”是中位数。 如果有4个组,则为两组中的每一组计算另外两个中位数。 但我不知道如果有5个组(箱),如果有更好的方法来编码它而不是计算中位数。
提前感谢您的回复。
答案 0 :(得分:0)
我确定这个问题可能比我要提出的问题更有效的算法,但我觉得对于一组35个值,范围从1到200,这个问题不需要最有效和优化的算法。一种直截了当,可以理解的方法就足够了。
首先,在列表中均匀分布4个分隔线(这可以在单独的列表中用4个值表示,指示它们的索引)。然后,将变量 changed 设置为true,然后输入主循环:更改时,执行逻辑。立即将更改设置为false(这将允许我们在达到最佳解决方案后终止)。现在,仍然在while循环中,有一个for循环,从0到3(包括)迭代,比较每个分频器两侧的高度。移动分隔线时,任一方向都会减小它们的差异,继续向该方向移动,并将更改设置为true。现在允许for循环重复所有分隔符,并在最外面的while循环中冲洗并重复循环,直到找不到更好的解决方案。
编辑:这是一些python代码试图做我上面解释的。您可能需要调整compare_bins函数以满足最平衡直方图的标准(我将其定义为所有相邻邻居之间差异的最小总和)。list_values = [10, 27, 59, 177, 185, 195, 54, 151, 15, 26, 105, 22, 32, 179, 92, 1, 115, 129, 152, 124, 100, 134, 175, 1, 149, 178, 28, 51, 90, 69, 128, 96, 8, 18, 38]
edges = [0, 7, 14, 21, 28, len(list_values)] # 0 and 34 are the ends of the list, and we do not change
def compare_bins(): # scores the difference in the histogram heights
global list_values, edges
score = 0
for bin_id in range(4):
idx = bin_id + 1
prev_bin = sum(list_values[edges[idx-1]:edges[idx]])
next_bin = sum(list_values[edges[idx]:edges[idx+1]])
score += abs(prev_bin - next_bin)
print(abs(prev_bin - next_bin))
return score
altered = True
while altered:
altered = False
for i in range(4):
old_diff = compare_bins()
idx = i + 1
edges[idx] -= 1
while compare_bins() < old_diff: # try moving the dividers left
edges[idx] -= 1
altered = True
edges[idx] += 2
while compare_bins() < old_diff: # try moving the dividers right
edges[idx] += 1
altered = True
edges[idx] -= 1