之前的方法只适合数据点只有一个中心的情况,有多个中心的数据可能会有反效果。
思路2:不考虑中心,按点和下一个点的距离进行判断和调整。
最终呈现的结果中相邻的两个点之间的距离占坐标轴总长度的1/25。依次排查各个点,如果和下一个点的距离小于这个最小值,就进行调整。
import math
from matplotlib import pyplot as plt
def find_min_dis(xdata):
"""找两点间允许的最小距离"""
return (max(xdata) - min(xdata))/25
def adjust_x(order_num, n, xdis):
"""以该点和下一个点连线的法线为参照,向两边分离上下的点
:param order_num: 数据列表, [序号, x坐标, y坐标];
:param n: 点的索引, 该点和下一个点距离需要加大;
:param xdis: 和允许的最小距离相差的值;
:return: 调整过点后的数据列表;
"""
for i in range(len(order_num)):
if i <= n:
# 调整比例应该为1/2,但是变化过大
order_num[i][1] -= xdis/20
elif i > n:
order_num[i][1] += xdis/20
return order_num
def adjacent_scatter(xdata):
"""某一个循环内的扩散"""
order_num = []
for i in range(len(xdata)):
order_num.append([i, xdata[i]])
order_num.sort(key=lambda x: x[1])
min_xdis = find_min_dis(xdata)
for i in range(len(xdata) - 1):
xdis = order_num[i+1][1] - order_num[i][1]
if xdis < min_xdis: # 坐标1的距离小于最小值
order_num = adjust_x(order_num, i, min_xdis-xdis)
order_num.sort(key=lambda x: x[0])
return [x[1] for x in order_num]
def main():
colors = ['#{0:0>2}{0:0>2}{0:0>2}'.format(i) for i in range(95)]
cycles = 0
while cycles < 20:
plt.scatter(xdata, ydata, c=colors)
plt.savefig(f'ok{cycles}.png')
plt.clf()
xdata, ydata = adjacent_scatter(xdata, ydata)
ydata, xdata = adjacent_scatter(ydata, xdata)
cycles += 1
上面三个图依次是初始点图、扩散2次后的点图和扩散9次后的点图。从结果能看到,这次的思路扩散很少的次数就能基本满足需求,扩散次数多了反而不是太好。对存在多个中心的数据点能较好地分散开,对于不要求精确度的分散已经能使用了。