随便的C# 发表于 2022-5-27 21:56:25

请教各位大佬:如何求最右边的所有点

本帖最后由 随便的C# 于 2022-5-27 21:57 编辑

比如图上有好几列点,我想获得最右边的所有点,例如方框里的点。
大佬们能给个解题思路吗?

landsat99 发表于 2022-5-31 15:55:33

本帖最后由 landsat99 于 2022-5-31 17:07 编辑

响应大佬,也来一段代码,,   Canopy算法的,也算一种簇类分析定质心。

Github : https://github.com/AlanConstantine/CanopyByPython

修改: 添加了核心参数T1,T2的粗略判断。取为整体矩阵 Data[:,0] 最大值和最小值区间的比例参数。
用楼上大咖的点位数据 再次试算。

# -*- coding: utf-8 -*-
# @Title:       Algorithm.Canopy :: Class.Canopy.py
# @From:      https://github.com/AlanConstantine/CanopyByPython
# @Date:      2022.05.31

import math
import random
import numpy as np
from datetime import datetime
from pprint import pprint as p
import matplotlib.pyplot as plt


class Canopy:

    def __init__(self, dataset):
      self.dataset = dataset
      self.t1 = 0
      self.t2 = 0

    # 设置初始阈值
    def setThreshold(self, t1, t2):
      if t1 > t2:
            self.t1 = t1
            self.t2 = t2
      else:
            print('t1 needs to be larger than t2!')

    # 使用欧式距离进行距离的计算
    def euclideanDistance(self, vec1, vec2):
      return math.sqrt(((vec1 - vec2)**2).sum())

    # 根据当前dataset的长度随机选择一个下标
    def getRandIndex(self):
      return random.randint(0, len(self.dataset) - 1)

    def clustering(self):
      if self.t1 == 0:
            print('Please set the threshold.')
      else:
            canopies = []# 用于存放最终归类结果
            while len(self.dataset) != 0:
                rand_index = self.getRandIndex()
                current_center = self.dataset# 随机获取一个中心点,定为P点
                current_center_list = []# 初始化P点的canopy类容器
                delete_list = []# 初始化P点的删除容器
                self.dataset = np.delete(
                  self.dataset, rand_index, 0)# 删除随机选择的中心点P
                for datum_j in range(len(self.dataset)):
                  datum = self.dataset
                  distance = self.euclideanDistance(
                        current_center, datum)# 计算选取的中心点P到每个点之间的距离
                  if distance < self.t1:
                        # 若距离小于t1,则将点归入P点的canopy类
                        current_center_list.append(datum)
                  if distance < self.t2:
                        delete_list.append(datum_j)# 若小于t2则归入删除容器
                # 根据删除容器的下标,将元素从数据集中删除
                self.dataset = np.delete(self.dataset, delete_list, 0)
                canopies.append((current_center, current_center_list))
      return canopies


def showCanopy(canopies, dataset, t1, t2):
    fig = plt.figure()
    sc = fig.add_subplot(111)
    colors = ['brown', 'green', 'blue', 'y', 'r', 'tan', 'dodgerblue', 'deeppink', 'orangered', 'peru', 'blue', 'y', 'r',
            'gold', 'dimgray', 'darkorange', 'peru', 'blue', 'y', 'r', 'cyan', 'tan', 'orchid', 'peru', 'blue', 'y', 'r', 'sienna']
    markers = ['*', 'h', 'H', '+', 'o', '1', '2', '3', ',', 'v', 'H', '+', '1', '2', '^',
               '<', '>', '.', '4', 'H', '+', '1', '2', 's', 'p', 'x', 'D', 'd', '|', '_']
    for i in range(len(canopies)):
      canopy = canopies
      center = canopy
      components = canopy
      sc.plot(center, center, marker=markers,
                color=colors, markersize=30)
      t1_circle = plt.Circle(
            xy=(center, center), radius=t1, color='dodgerblue', fill=False)
      t2_circle = plt.Circle(
            xy=(center, center), radius=t2, color='skyblue', alpha=0.2)
      sc.add_artist(t1_circle)
      sc.add_artist(t2_circle)
      for component in components:
            sc.plot(component, component,
                  marker=markers, color=colors, markersize=1.5)
    maxvalue = np.amax(dataset)
    minvalue = np.amin(dataset)
    plt.xlim(minvalue - t1, maxvalue + t1)
    plt.ylim(minvalue - t1, maxvalue + t1)
    plt.show()


# 随机生成600个二维[0,1)平面点
# dataset = np.random.rand(600, 2)
dataset = np.array([[-3,0], [-2.5,1], [-3.5,3], [-0.5,0], , , , , ])

if __name__ == '__main__':
    NMax = np.max(dataset[:, 0])
    NMin = np.min(dataset[:, 0])
    t1 = (NMax - NMin) * 0.7
    t2 = t1 * 0.75
    gc = Canopy(dataset)
    gc.setThreshold(t1, t2)
    canopies = gc.clustering()
    print('Get %s initial centers.' % len(canopies))
    showCanopy(canopies, dataset, t1, t2)





红框内,指定的参数T1 ,T2。   缩小区间,质心数量增加。

另外,聚类分析好像还有 Kmeans++ ,Kmeans II 等算法估CenterPoi。






qjchen 发表于 2022-5-31 12:09:59

革天明 发表于 2022-5-29 08:23
看了讨论,楼主想要的是不给定公差的情况下,自行计算,请参考K-means进行聚类即可

谢谢分享~


之前觉得应该是用机器学习或者深度学习可能才能得到这个,但之前没有认真学过,不懂聚类。

于是学习了一下,颇有收获

以下是用ANACONDA的SPYDER编写PYTHON代码,主要用的sklearn

# 参考 https://www.tutorialspoint.com/machine_learning_with_python/machine_learning_with_python_clustering_algorithms_k_means.htm

import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans

XY=np.array([[-3,0], [-2.5,1], [-3.5,3], [-0.5,0], , , , , ])

#显示原始数据
plt.scatter(XY[:, 0], XY[:, 1], s = 30);
plt.show()

#人为定义为3组,y_kmeans就是预测的分组
kmeans = KMeans(n_clusters = 3)
kmeans.fit(XY)
y_kmeans = kmeans.predict(XY)

#显示聚类后的数据
plt.scatter(XY[:, 0], XY[:, 1], c = y_kmeans, s = 30, cmap = 'rainbow')
#显示聚类后的类中心
centers = kmeans.cluster_centers_
plt.scatter(centers[:, 0], centers[:, 1], c = 'blue', s = 100, alpha = 0.9);
plt.show()


结果如下:左是归类前,右是归类后


不过这个里面,人为规定了类数是3个,不知道有没有更好的自动算类的方法,但看到一般的KMEANS算法好像都有这个

后续:
假如用飞狐兄的PYCAD,估计可以编入PY插件
或者可以试试看ML.NET,看看编个C#插件可能也可以

landsat99 发表于 2022-5-28 11:11:20

几个想法聊聊。抛砖引玉。。

1.   简单法。给出选区 -> 选区x轴右侧比如所有点
2.   均值/方差选择。给定两点(用直线、两点、窗口方式都OK)本质是给定均值和方差或方差的函数. 即可找到符合你要求的点。算量基本是O(N)
3.   色阶法。 分析全图所有点得到几种分布指标 -> 以分布指标极值附近某点为均值,方差为参数选择。 类似PS的图片色阶算法。算量约O(2~3N)。
      如果第二步不用方差鲁棒定界,指定算法或AI识别等其他,比如离散动力学估界,会指数级增加算量O(N^2) .O(N^2.5)。

算法无上限,看应用场景、成本

烟盒迷唇 发表于 2022-5-28 06:43:48

X坐标值最大的点啊

随便的C# 发表于 2022-5-28 17:47:27

烟盒迷唇 发表于 2022-5-28 06:43
X坐标值最大的点啊

这只能求到最大的一个点,而不是一列点,我想求的就是最右列的所有点。

xj6019 发表于 2022-5-28 17:59:29

烟盒迷唇 发表于 2022-5-28 06:43
X坐标值最大的点啊

这个法应该最简单

随便的C# 发表于 2022-5-28 18:09:12

landsat99 发表于 2022-5-28 11:11
几个想法聊聊。抛砖引玉。。

1.   简单法。给出选区 -> 选区x轴右侧比如所有点


方差我感觉不太行,因为就如那张示意图一样,假如最左一列的所有点的X坐标相同的话,两点关于X坐标最小的方差就是最左列的点了。

自贡黄明儒 发表于 2022-5-28 18:09:56

随便的C# 发表于 2022-5-28 17:47
这只能求到最大的一个点,而不是一列点,我想求的就是最右列的所有点。

给X值一个公差,差值范内所有点为一列、

随便的C# 发表于 2022-5-28 18:36:00

自贡黄明儒 发表于 2022-5-28 18:09
给X值一个公差,差值范内所有点为一列、

这样的话就得每次都定义不同的方差范围

革天明 发表于 2022-5-29 08:23:55

看了讨论,楼主想要的是不给定公差的情况下,自行计算,请参考K-means进行聚类即可

随便的C# 发表于 2022-5-29 21:11:50

革天明 发表于 2022-5-29 08:23
看了讨论,楼主想要的是不给定公差的情况下,自行计算,请参考K-means进行聚类即可

感谢大佬的点拨!
页: [1] 2
查看完整版本: 请教各位大佬:如何求最右边的所有点