精华内容
下载资源
问答
  • 经纬度聚类

    千次阅读 2019-06-21 11:31:30
    1. 经纬度数据 xy = np.array([[29.060703, 113.348653], [22.5445697, 114.0545346], [43.8882168, 125.3182578], [30.5951051, 114.2999353], [26.0774954, 119.2918215], [23.0444712, ...

    1. 经纬度数据

    xy = np.array([[29.060703, 113.348653], [22.5445697, 114.0545346], 
                  [43.8882168, 125.3182578], [30.5951051, 114.2999353], 
                  [26.0774954, 119.2918215], [23.0444712, 113.7465512], 
                  [42.0151733, 121.6452868], [32.0609736, 118.7916458], 
                  [22.5445697, 114.0545346], [39.1235635, 117.1980785], 
                  [36.6507007, 117.1140042], [31.2252985, 121.4890497], 
                  [20.0423626, 110.3409936], [22.5213807, 113.3656141], 
                  [29.3595966, 115.9428552], [26.5814112, 106.7052544], 
                  [23.1301964, 113.2592945], [41.494444, 121.615278], 
                  [23.0444712, 113.7465512], [39.906217, 116.3912757], 
                  [22.5213807, 113.3656141], [9.6153904, 112.970189230798], 
                  [39.1235635, 117.1980785], [30.466238, 111.686209455868], 
                  [45.7656666, 126.6160584], [32.5664035, 128.899626584395], 
                  [43.8882168, 125.3182578], [23.0515551, 112.4728451], 
                  [31.32640095, 120.990580800174], [27.9958689, 120.6915792], 
                  [39.906217, 116.3912757], [22.5445697, 114.0545346], 
                  [35.218039, 111.053715], [39.906217, 116.3912757], 
                  [31.9827896, 120.8904588], [31.458932, 104.750108], 
                  [34.7591877, 113.6524076], [27.9958689, 120.6915792], 
                  [39.906217, 116.3912757], [39.1235635, 117.1980785], 
                  [32.0609736, 118.7916458], [31.8129864, 119.9692045], 
                  [31.8782976, 120.5514595], [39.1235635, 117.1980785], 
                  [29.5585712, 106.5492822], [46.8087794, 130.3734556], 
                  [31.2252985, 121.4890497], [39.1235635, 117.1980785], 
                  [34.3468421, 108.9365887], [22.5445697, 114.0545346], 
                  [31.8129864, 119.9692045], [39.906217, 116.3912757], 
                  [33.387124, 104.9313723], [31.2252985, 121.4890497], 
                  [25.4342199, 119.0074625], [43.8254059, 87.614569], 
                  [39.906217, 116.3912757], [39.906217, 116.3912757], 
                  [24.4586961, 118.0745391], [40.01363995, 119.35495441411], 
                  [34.7591877, 113.6524076], [30.5951051, 114.2999353], 
                  [30.65093955, 120.783165577059], [39.906217, 116.3912757], 
                  [30.5951051, 114.2999353], [29.5585712, 106.5492822], 
                  [23.1301964, 113.2592945], [39.1235635, 117.1980785], 
                  [28.6581723, 121.4163876], [40.6549157, 109.8344586], 
                  [39.906217, 116.3912757], [22.8211654, 108.3159756], 
                  [32.0609736, 118.7916458], [23.1301964, 113.2592945], 
                  [38.04, 114.47], [30.7031196, 111.2750181], 
                  [34.0472604, 113.804958141593], [26.0774954, 119.2918215], 
                  [34.3468421, 108.9365887], [39.906217, 116.3912757], 
                  [23.0247687, 113.1146335], [27.13543065, 105.565762465037], 
                  [32.0609736, 118.7916458], [43.6392011, 122.2497308], 
                  [29.8622194, 121.6203873], [30.2134399, 115.0670135], 
                  [38.21211485, 116.838327521023], [21.9745252, 113.931350084859], 
                  [29.7275361, 115.9913134], [31.2252985, 121.4890497], 
                  [28.1979483, 112.97133], [26.6655699, 119.5224895], 
                  [29.75929015, 120.51582161865], [29.5585712, 106.5492822], 
                  [36.4441808, 115.9642007]]
        )
    

    2. 坐标聚类生成子图

    for k in range(2,6):    #选择连续不同的 k 值
    
        matplotlib.rcParams['font.sans-serif']=['SimHei']
        
        if k == 2:
            ax = fig.add_subplot(221)
            ax.set_title('聚类图(2个簇点)')
        if k == 3:
            ax = fig.add_subplot(222)
            ax.set_title('聚类图(3个簇点)')
        if k == 4:
            ax = fig.add_subplot(223)
            ax.set_title('聚类图(4个簇点)')
        if k == 5:
            ax = fig.add_subplot(224)
            ax.set_title('聚类图(5个簇点)')
            
        clf = KMeans(n_clusters=k) #n_clusters用于指定聚类的簇数
        s = clf.fit(xy) #加载数据集合
        numSamples=len(xy)
        centroids = clf.labels_
       
        mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
        #画出所有样例点 属于同一分类的绘制同样的颜色
        for i in range(numSamples):
            ax.plot(xy[i][1], xy[i][0], mark[clf.labels_[i]]) #mark[markIndex])
            
        mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '<b', 'pb']
        # 画出质点,用特殊图型
        centroids =  clf.cluster_centers_
        for i in range(k):
            ax.plot(centroids[i][1], centroids[i][0], mark[i], markersize = 12)
            
    plt.subplots_adjust(wspace =0.3, hspace =0.5)#调整子图间距
    plt.savefig('聚类图.png', dpi=200)  
    
    plt.show()   
    

    3. 结果展示

    在这里插入图片描述

    展开全文
  • 有如下中国城市数据,要求按照经纬度对中国二级城市聚类: 首先显示城市的分布图 观察设置k的合理值 对数据进行聚类,并显示图形聚类结果 输出每一类对应的城市 完整数据在本篇博客最后 北京市 北京市 北纬...

    题目:数据仓库与挖掘实验 —— 聚类分析

    1. 有如下中国城市数据,要求按照经纬度对中国二级城市聚类:
    2. 首先显示城市的分布图
    3. 观察设置k的合理值
    4. 对数据进行聚类,并显示图形聚类结果
    5. 输出每一类对应的城市
    6. 完整数据在本篇博客最后
    7.     北京市 北京市 北纬39.55 东经116.24

          福建省 福州 北纬26.05 东经119.18

          福建省 长乐 北纬25.58 东经119.31

          福建省 福安 北纬27.06 东经119.39

          福建省 福清 北纬25.42 东经119.23

          福建省 建瓯 北纬27.03 东经118.20

          福建省 建阳 北纬27.21 东经118.07

     

    代码分析:

    1.显示城市分布图

    import pandas as pd
    import matplotlib.pyplot as plt
    
    inputfile = './data/secondary_province_data.xlsx' 
    outputfile = './tmp2/data_type_latitude_longitude.xls'
    
    latitude = pd.read_excel(inputfile, usecols=[3])    #北纬
    longtitude = pd.read_excel(inputfile, usecols=[4])  #东经
    
    plt.figure(figsize=(10, 10), dpi=100)
    plt.scatter(longtitude, latitude, marker='*', c='red')
    plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
    plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
    plt.xlabel("东经", fontdict={'size': 16})
    plt.ylabel("北纬", fontdict={'size': 16})
    plt.title("中国城市分布图", fontdict={'size': 20})
    plt.show()

     

    2. 聚类分析

    
    
    import pandas as pd
    
    inputfile = './data/secondary_province_data.xlsx' 
    outputfile = './tmp2/data_type_latitude_longitude.xls'
    
    k = 3 #聚类类别
    iteration = 500 #聚类最大循环次数
    
    data = pd.read_excel(inputfile, usecols=[0, 3, 4], index_col=[0])
    data2 = pd.read_excel(inputfile)
    # print(data2['secondary'])
    # print(data2['id'])
    # print(data2.columns)
    
    data_zs = 1.0*(data - data.mean())/data.std()#数据标准化
    # print(data_zs)
    
    from sklearn.cluster import KMeans
    model = KMeans(n_clusters = k, n_jobs = 1, max_iter = iteration) #分为k类
    model.fit(data_zs) #开始聚类
    
    #简单打印结果
    r1 = pd.Series(model.labels_).value_counts() #统计各个类别的数目
    r2 = pd.DataFrame(model.cluster_centers_) #找出聚类中心
    # print(r1)
    r = pd.concat([r2, r1], axis = 1) #横向连接(0是纵向),得到聚类中心对应的类别下的数目
    # print(data.columns)
    r.columns = list(data.columns) + [u'类别数目'] #重命名表头
    print(r)
    
    #详细输出原始数据及其类别
    r = pd.concat([data, pd.Series(model.labels_, index = data.index)], axis = 1)  #详细输出每个样本对应的类别
    r.columns = list(data.columns) + [u'聚类类别']#重命名表头
    
    r.to_excel(outputfile) #保存结果
    #  + [data2[u'secondary']]  
    print(r)
    
    
    def density_plot(data): #自定义作图函数
      import matplotlib.pyplot as plt
      plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
      plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
      p = data.plot(kind='kde', linewidth = 2, subplots = True, sharex = False)
    #   [p[i].set_ylabel(u'密度') for i in range(k)]
      plt.legend()
      return plt
    
    pic_output = './tmp2/pd_' #概率密度图文件名前缀
    for i in range(3): 
     density_plot(data[r[u'聚类类别']==i]).savefig(u'%s%s.png' %(pic_output, i))

     

    3. 聚类结果图

    inputfile = './tmp2/data_type_latitude_longitude.xls' #销量及其他属性数据
    df = pd.read_excel(inputfile, usecols=[0, 1, 2, 3])
    # print(df['id'])
    # print(df.columns)
    
    x0 = df.loc[df['聚类类别']==0,['longitude']]
    y0 = df.loc[df['聚类类别']==0,['latitude']]
    x1 = df.loc[df['聚类类别']==1,['longitude']]
    y1 = df.loc[df['聚类类别']==1,['latitude']]
    x2 = df.loc[df['聚类类别']==2,['longitude']]
    y2 = df.loc[df['聚类类别']==2,['latitude']]
    
    plt.figure(figsize=(10, 10), dpi=100)
    plt.scatter(x0, y0, c = "red", marker='o', label='label0')
    plt.scatter(x1, y1, c = "blue", marker='*', label='label1')
    plt.scatter(x2, y2, c = "green", marker='+', label='label2')
    plt.xlabel("东经", fontdict={'size': 16})
    plt.ylabel("北纬", fontdict={'size': 16})
    plt.legend(loc=2)
    plt.title("聚类结果图", fontdict={'size': 20})
    plt.show()

     

    4. 打印标签对应的城市

    res = pd.read_excel('./tmp2/data_type_latitude_longitude.xls')
    # print(res)
    # print(type(res))
    res.insert(1, 'secondary', data2['secondary'])
    # print(res)
    
    for i in range(k):
        print(res.loc[res['聚类类别']==i])

     

    完整数据 :

        北京市 北京市 北纬39.55 东经116.24
        福建省 福州 北纬26.05 东经119.18
        福建省 长乐 北纬25.58 东经119.31
        福建省 福安 北纬27.06 东经119.39
        福建省 福清 北纬25.42 东经119.23
        福建省 建瓯 北纬27.03 东经118.20
        福建省 建阳 北纬27.21 东经118.07
        福建省 晋江 北纬24.49 东经118.35
        福建省 龙海 北纬24.26 东经117.48
        福建省 龙岩 北纬25.06 东经117.01
        福建省 南安 北纬24.57 东经118.23
        福建省 南平 北纬26.38 东经118.10
        福建省 宁德 北纬26.39 东经119.31
        福建省 莆田 北纬24.26 东经119.01
        福建省 泉州 北纬24.56 东经118.36
        福建省 三明 北纬26.13 东经117.36
        福建省 邵武 北纬27.20 东经117.29
        福建省 石狮 北纬24.44 东经118.38
        福建省 武夷山 北纬27.46 东经118.02
        福建省 厦门 北纬24.27 东经118.06
        福建省 永安 北纬25.58 东经117.23
        福建省 漳平 北纬25.17 东经117.24
        福建省 漳州 北纬24.31 东经117.39
        甘肃省 兰州 北纬36.04 东经103.51
        甘肃省 白银 北纬36.33 东经104.12
        甘肃省 敦煌 北纬40.08 东经94.41
        甘肃省 嘉峪关 北纬39.48 东经98.14
        甘肃省 金昌 北纬38.28 东经102.10
        甘肃省 酒泉 北纬39.44 东经98.31
        甘肃省 临夏 北纬35.37 东经103.12
        甘肃省 平凉 北纬35.32 东经106.40
        甘肃省 天水 北纬34.37 东经105.42
        甘肃省 武威 北纬37.56 东经102.39
        甘肃省 西峰 北纬35.45 东经107.40
        甘肃省 玉门 北纬39.49 东经97.35
        甘肃省 张掖 北纬38.56 东经100.26
        广东省 广州 北纬23.08 东经113.14
        广东省 潮阳 北纬23.16 东经116.36
        广东省 潮州 北纬23.40 东经116.38
        广东省 澄海 北纬23.28 东经116.46
        广东省 从化 北纬23.33 东经113.33
        广东省 东莞 北纬23.02 东经113.45
        广东省 恩平 北纬22.12 东经112.19
        广东省 佛山 北纬23.02 东经113.06
        广东省 高明 北纬22.53 东经112.50
        广东省 高要 北纬23.02 东经112.26
        广东省 高州 北纬21.54 东经110.50
        广东省 鹤山 北纬22.46 东经112.57
        广东省 河源 北纬23.43 东经114.41
        广东省 花都 北纬23.23 东经113.12
        广东省 化州 北纬21.39 东经110.37
        广东省 惠阳 北纬22.48 东经114.28
        广东省 惠州 北纬23.05 东经114.22
        广东省 江门 北纬22.35 东经113.04
        广东省 揭阳 北纬22.32 东经116.21
        广东省 开平 北纬22.22 东经112.40
        广东省 乐昌 北纬25.09 东经113.21
        广东省 雷州 北纬20.54 东经110.04
        广东省 廉江 北纬21.37 东经110.17
        广东省 连州 北纬24.48 东经112.23
        广东省 罗定 北纬22.46 东经111.33
        广东省 茂名 北纬21.40 东经110.53
        广东省 梅州 北纬24.19 东经116.07
        广东省 南海 北纬23.01 东经113.09
        广东省 番禺 北纬22.57 东经113.22
        广东省 普宁 北纬23.18 东经116.10
        广东省 清远 北纬23.42 东经113.01
        广东省 三水 北纬23.10 东经112.52
        广东省 汕头 北纬23.22 东经116.41
        广东省 汕尾 北纬22.47 东经115.21
        广东省 韶关 北纬24.48 东经113.37
        广东省 深圳 北纬22.33 东经114.07
        广东省 顺德 北纬22.50 东经113.15
        广东省 四会 北纬23.21 东经112.41
        广东省 台山 北纬22.15 东经112.48
        广东省 吴川 北纬21.26 东经110.47
        广东省 新会 北纬22.32 东经113.01
        广东省 兴宁 北纬24.09 东经115.43
        广东省 阳春 北纬22.10 东经111.48
        广东省 阳江 北纬21.50 东经111.58
        广东省 英德 北纬24.10 东经113.22
        广东省 云浮 北纬22.57 东经112.02
        广东省 增城 北纬23.18 东经113.49
        广东省 湛江 北纬21.11 东经110.24
        广东省 肇庆 北纬23.03 东经112.27
        广东省 中山 北纬22.31 东经113.22
        广东省 珠海 北纬22.17 东经113.34
        海南省 海口 北纬20.02 东经110.20
        海南省 儋州 北纬19.31 东经109.34
        海南省 琼海 北纬19.14 东经110.28
        海南省 琼山 北纬19.59 东经110.21
        海南省 三亚 北纬18.14 东经109.31
        海南省 通什 北纬18.46 东经109.31
        河北省 石家庄 北纬38.02 东经114.30
        河北省 安国 北纬38.24 东经115.20
        河北省 保定 北纬38.51 东经115.30
        河北省 霸州 北纬39.06 东经116.24
        河北省 泊头 北纬38.04 东经116.34
        河北省 沧州 北纬38.18 东经116.52
        河北省 承德 北纬40.59 东经117.57
        河北省 定州 北纬38.30 东经115.00
        河北省 丰南 北纬39.34 东经118.06
        河北省 高碑店 北纬39.20 东经115.51
        河北省 蒿城 北纬38.02 东经114.50
        河北省 邯郸 北纬36.36 东经114.28
        河北省 河间 北纬38.26 东经116.05
        河北省 衡水 北纬37.44 东经115.42
        河北省 黄骅 北纬38.21 东经117.21
        河北省 晋州 北纬38.02 东经115.02
        河北省 冀州 北纬37.34 东经115.33
        河北省 廓坊 北纬39.31 东经116.42
        河北省 鹿泉 北纬38.04 东经114.19
        河北省 南宫 北纬37.22 东经115.23
        河北省 秦皇岛 北纬39.55 东经119.35
        河北省 任丘 北纬38.42 东经116.07
        河北省 三河 北纬39.58 东经117.04
        河北省 沙河 北纬36.51 东经114.30
        河北省 深州 北纬38.01 东经115.32
        河北省 唐山 北纬39.36 东经118.11
        河北省 武安 北纬36.42 东经114.11
        河北省 邢台 北纬37.04 东经114.30
        河北省 辛集 北纬37.54 东经115.12
        河北省 新乐 北纬38.20 东经114.41
        河北省 张家口 北纬40.48 东经114.53
        河北省 涿州 北纬39.29 东经115.59
        河北省 遵化 北纬40.11 东经117.58
        黑龙江省 哈尔滨 北纬45.44 东经126.36
        黑龙江省 阿城 北纬45.32 东经126.58
        黑龙江省 安达 北纬46.24 东经125.18
        黑龙江省 北安 北纬48.15 东经126.31
        黑龙江省 大庆 北纬46.36 东经125.01
        黑龙江省 富锦 北纬47.15 东经132.02
        黑龙江省 海林 北纬44.35 东经129.21
        黑龙江省 海伦 北纬47.28 东经126.57
        黑龙江省 鹤岗 北纬47.20 东经130.16
        黑龙江省 黑河 北纬50.14 东经127.29
        黑龙江省 佳木斯 北纬46.47 东经130.22
        黑龙江省 鸡西 北纬45.17 东经130.57
        黑龙江省 密山 北纬45.32 东经131.50
        黑龙江省 牡丹江 北纬44.35 东经129.36
        黑龙江省 讷河 北纬48.29 东经124.51
        黑龙江省 宁安 北纬44.21 东经129.28
        黑龙江省 齐齐哈尔 北纬47.20 东经123.57
        黑龙江省 七台河 北纬45.48 东经130.49
        黑龙江省 双城 北纬45.22 东经126.15
        黑龙江省 尚志 北纬45.14 东经127.55
        黑龙江省 双鸭山 北纬46.38 东经131.11
        黑龙江省 绥芬河 北纬44.25 东经131.11
        黑龙江省 绥化 北纬46.38 东经126.59
        黑龙江省 铁力 北纬46.59 东经128.01
        黑龙江省 同江 北纬47.39 东经132.30
        黑龙江省 五常 北纬44.55 东经127.11
        黑龙江省 五大连池 北纬48.38 东经126.07
        黑龙江省 伊春 北纬47.42 东经128.56
        黑龙江省 肇东 北纬46.04 东经125.58
        湖北省 武汉 北纬30.35 东经114.17
        湖北省 安陆 北纬31.15 东经113.41
        湖北省 当阳 北纬30.50 东经111.47
        湖北省 丹江口 北纬32.33 东经108.30
        湖北省 大冶 北纬30.06 东经114.58
        湖北省 恩施 北纬30.16 东经109.29
        湖北省 鄂州 北纬30.23 东经114.52
        湖北省 广水 北纬31.37 东经113.48
        湖北省 洪湖 北纬29.48 东经113.27
        湖北省 黄石 北纬30.12 东经115.06
        湖北省 黄州 北纬30.27 东经114.52
        湖北省 荆门 北纬31.02 东经112.12
        湖北省 荆沙 北纬30.18 东经112.16
        湖北省 老河口 北纬32.23 东经111.40
        湖北省 利川 北纬30.18 东经108.56
        湖北省 麻城 北纬31.10 东经115.01
        湖北省 浦圻 北纬29.42 东经113.51
        湖北省 潜江 北纬30.26 东经112.53
        湖北省 石首 北纬29.43 东经112.24
        湖北省 十堰 北纬32.40 东经110.47
        湖北省 随州 北纬31.42 东经113.22
        湖北省 天门 北纬60.39 东经113.10
        湖北省 武穴 北纬29.51 东经115.33
        湖北省 襄樊 北纬32.02 东经112.08
        湖北省 咸宁 北纬29.53 东经114.17
        湖北省 仙桃 北纬30.22 东经113.27
        湖北省 孝感 北纬30.56 东经113.54
        湖北省 宜昌 北纬30.42 东经111.17
        湖北省 宜城 北纬31.42 东经112.15
        湖北省 应城 北纬30.57 东经113.33
        湖北省 枣阳 北纬32.07 东经112.44
        湖北省 枝城 北纬30.23 东经111.27
        湖北省 钟祥 北纬31.10 东经112.34
        江苏省 南京 北纬32.03 东经118.46
        江苏省 常熟 北纬31.39 东经120.43
        江苏省 常州 北纬31.47 东经119.58
        江苏省 丹阳 北纬32.00 东经119.32
        江苏省 东台 北纬32.51 东经120.19
        江苏省 高邮 北纬32.47 东经119.27
        江苏省 海门 北纬31.53 东经121.09
        江苏省 淮安 北纬33.30 东经119.09
        江苏省 淮阴 北纬33.36 东经119.02
        江苏省 江都 北纬32.26 东经119.32
        江苏省 姜堰 北纬32.34 东经120.08
        江苏省 江阴 北纬31.54 东经120.17
        江苏省 靖江 北纬32.02 东经120.17
        江苏省 金坛 北纬31.46 东经119.33
        江苏省 昆山 北纬31.23 东经120.57
        江苏省 连去港 北纬34.36 东经119.10
        江苏省 溧阳 北纬31.26 东经119.29
        江苏省 南通 北纬32.01 东经120.51
        江苏省 邳州 北纬34.19 东经117.59
        江苏省 启乐 北纬31.48 东经121.39
        江苏省 如皋 北纬32.23 东经120.33
        江苏省 宿迁 北纬33.58 东经118.18
        江苏省 苏州 北纬31.19 东经120.37
        江苏省 太仓 北纬31.27 东经121.06
        江苏省 泰兴 北纬32.10 东经120.01
        江苏省 泰州 北纬32.30 东经119.54
        江苏省 通州 北纬32.05 东经121.03
        江苏省 吴江 北纬31.10 东经120.39
        江苏省 无锡 北纬31.34 东经120.18
        江苏省 兴化 北纬32.56 东经119.50
        江苏省 新沂 北纬34.22 东经118.20
        江苏省 徐州 北纬34.15 东经117.11
        江苏省 盐在 北纬33.22 东经120.08
        江苏省 扬中 北纬32.14 东经119.49
        江苏省 扬州 北纬32.23 东经119.26
        江苏省 宜兴 北纬31.21 东经119.49
        江苏省 仪征 北纬32.16 东经119.10
        江苏省 张家港 北纬31.52 东经120.32
        江苏省 镇江 北纬32.11 东经119.27
        内自治区 呼和浩特 北纬40.48 东经111.41
        内自治区 包头 北纬40.39 东经109.49
        内自治区 赤峰 北纬42.17 东经118.58
        内自治区 东胜 北纬39.48 东经109.59
        内自治区 二连浩特 北纬43.38 东经111.58
        内自治区 额尔古纳 北纬50.13 东经120.11
        内自治区 丰镇 北纬40.27 东经113.09
        内自治区 根河 北纬50.48 东经121.29
        内自治区 海拉尔 北纬49.12 东经119.39
        内自治区 霍林郭勒 北纬45.32 东经119.38
        内自治区 集宁 北纬41.02 东经113.06
        内自治区 临河 北纬40.46 东经107.22
        内自治区 满洲里 北纬49.35 东经117.23
        内自治区 通辽 北纬43.37 东经122.16
        内自治区 乌兰浩特 北纬46.03 东经122.03
        内自治区 乌海 北纬39.40 东经106.48
        内自治区 锡林浩特 北纬43.57 东经116.03
        内自治区 牙克石 北纬49.17 东经120.40
        内自治区 扎兰屯 北纬48.00 东经122.47
        宁夏自治区 银川 北纬38.27 东经106.16
        宁夏自治区 青铜峡 北纬37.56 东经105.59
        宁夏自治区 石嘴山 北纬39.02 东经106.22
        宁夏自治区 吴忠 北纬37.59 东经106.11
        青海省 西宁 北纬36.38 东经101.48
        青海省 德令哈 北纬37.22 东经97.23
        青海省 格尔木 北纬36.26 东经94.55
        山东省 济南 北纬36.40 东经117.00
        山东省 安丘 北纬36.25 东经119.12
        山东省 滨州 北纬37.22 东经118.02
        山东省 昌邑 北纬39.52 东经119.24
        山东省 德州 北纬37.26 东经116.17
        山东省 东营 北纬37.27 东经118.30
        山东省 肥城 北纬36.14 东经116.46
        山东省 高密 北纬36.22 东经119.44
        山东省 菏泽 北纬35.14 东经115.26
        山东省 胶南 北纬35.53 东经119.58
        山东省 胶州 北纬36.17 东经120.00
        山东省 即墨 北纬36.22 东经120.28
        山东省 济宁 北纬35.23 东经116.33
        山东省 莱芜 北纬36.12 东经117.40
        山东省 莱西 北纬36.52 东经120.31
        山东省 莱阳 北纬36.58 东经120.42
        山东省 莱州 北纬37.10 东经119.57
        山东省 乐陵 北纬37.44 东经117.12
        山东省 聊城 北纬36.26 东经115.57
        山东省 临清 北纬36.51 东经115.42
        山东省 临沂 北纬35.03 东经118.20
        山东省 龙口 北纬37.39 东经120.21
        山东省 蓬莱 北纬37.48 东经120.45
        山东省 平度 北纬36.47 东经119.58
        山东省 青岛 北纬36.03 东经120.18
        山东省 青州 北纬36.42 东经118.28
        山东省 曲阜 北纬35.36 东经116.58
        山东省 日照 北纬35.23 东经119.32
        山东省 荣成 北纬37.10 东经122.25
        山东省 乳山 北纬36.54 东经121.31
        山东省 寿光 北纬36.53 东经118.44
        山东省 泰安 北纬36.11 东经117.08
        山东省 滕州 北纬35.06 东经117.09
        山东省 潍坊 北纬36.43 东经119.06
        山东省 威海 北纬37.31 东经122.07
        山东省 文登 北纬37.12 东经122.03
        山东省 新泰 北纬35.54 东经117.45
        山东省 烟台 北纬37.32 东经121.24
        山东省 兖州 北纬35.32 东经116.49
        山东省 禹城 北纬36.56 东经116.39
        山东省 枣庄 北纬34.52 东经117.33
        山东省 章丘 北纬36.43 东经117.32
        山东省 招远 北纬37.21 东经120.23
        山东省 诸城 北纬35.59 东经119.24
        山东省 淄博 北纬36.48 东经118.03
        山东省 邹城 北纬35.24 东经116.58
        陕西省 西安 北纬34.17 东经108.57
        陕西省 安康 北纬32.41 东经109.01
        陕西省 宝鸡 北纬34.22 东经107.09
        陕西省 韩城 北纬35.28 东经110.27
        陕西省 汉中 北纬33.04 东经107.01
        陕西省 华阴 北纬34.34 东经110.05
        陕西省 商州 北纬33.52 东经109.57
        陕西省 铜川 北纬35.06 东经109.07
        陕西省 渭南 北纬34.30 东经109.30
        陕西省 咸阳 北纬34.20 东经108.43
        陕西省 兴平 北纬34.18 东经108.29
        陕西省 延安 北纬36.35 东经109.28
        陕西省 榆林 北纬38.18 东经109.47
        上海市 上海市 北纬31.14 东经121.29
        四川省 成都 北纬30.40 东经104.04
        四川省 巴中 北纬31.51 东经106.43
        四川省 崇州 北纬30.39 东经103.40
        四川省 达川 北纬31.14 东经107.29
        四川省 德阳 北纬31.09 东经104.22
        四川省 都江堰 北纬31.01 东经103.37
        四川省 峨眉山 北纬29.36 东经103.29
        四川省 涪陵 北纬29.42 东经107.22
        四川省 广汉 北纬30.58 东经104.15
        四川省 广元 北纬32.28 东经105.51
        四川省 华蓥 北纬30.26 东经106.44
        四川省 简阳 北纬30.24 东经104.32
        四川省 江油 北纬31.48 东经104.42
        四川省 阆中 北纬31.36 东经105.58
        四川省 乐山 北纬29.36 东经103.44
        四川省 泸州 北纬28.54 东经105.24
        四川省 绵阳 北纬31.30 东经104.42
        四川省 南充 北纬30.49 东经106.04
        四川省 内江 北纬29.36 东经105.02
        四川省 攀枝花 北纬26.34 东经101.43
        四川省 彭州 北纬30.59 东经103.57
        四川省 邛崃 北纬30.26 东经103.28
        四川省 遂宁 北纬30.31 东经105.33
        四川省 万县 北纬30.50 东经108.21
        四川省 万源 北纬32.03 东经108.03
        四川省 西昌 北纬27.54 东经102.16
        四川省 雅安 北纬29.59 东经102.59
        四川省 宜宾 北纬28.47 东经104.34
        四川省 自贡 北纬29.23 东经104.46
        四川省 资阳 北纬30.09 东经104.38
        台湾省 台北市 北纬25.03 东经121.30
        天津市 天津市 北纬39.02 东经117.12
        西藏自治区 拉萨 北纬29.39 东经91.08
        西藏自治区 日喀则 北纬29.16 东经88.51
        香港 香港市 北纬21.23 东经115.12
        新疆自治区 乌鲁木齐 北纬43.45 东经87.36
        新疆自治区 阿克苏 北纬41.09 东经80.19
        新疆自治区 阿勒泰 北纬47.50 东经88.12
        新疆自治区 阿图什 北纬39.42 东经76.08
        新疆自治区 博乐 北纬44.57 东经82.08
        新疆自治区 昌吉 北纬44.02 东经87.18
        新疆自治区 阜康 北纬44.09 东经87.58
        新疆自治区 哈密 北纬42.50 东经93.28
        新疆自治区 和田 北纬37.09 东经79.55
        新疆自治区 克拉玛依 北纬45.36 东经84.51
        新疆自治区 喀什 北纬39.30 东经75.59
        新疆自治区 库尔勒 北纬41.46 东经86.07
        新疆自治区 奎屯 北纬44.27 东经84.56
        新疆自治区 石河子 北纬44.18 东经86.00
        新疆自治区 塔城 北纬46.46 东经82.59
        新疆自治区 吐鲁番 北纬42.54 东经89.11
        新疆自治区 伊宁 北纬43.55 东经81.20
        云南省 昆明 北纬25.04 东经102.42
        云南省 保山 北纬25.08 东经99.10
        云南省 楚雄 北纬25.01 东经101.32
        云南省 大理 北纬25.34 东经100.13
        云南省 东川 北纬26.06 东经103.12
        云南省 个旧 北纬23.21 东经103.09
        云南省 景洪 北纬22.01 东经100.48
        云南省 开远 北纬23.43 东经103.13
        云南省 曲靖 北纬25.30 东经103.48
        云南省 瑞丽 北纬24.00 东经97.50
        云南省 思茅 北纬22.48 东经100.58
        云南省 畹町 北纬24.06 东经98.04
        云南省 宣威 北纬26.13 东经104.06
        云南省 玉溪 北纬24.22 东经102.32
        云南省 昭通 北纬27.20 东经103.42
        浙江省 杭州 北纬30.16 东经120.10
        浙江省 慈溪 北纬30.11 东经121.15
        浙江省 东阳 北纬29.16 东经120.14
        浙江省 奉化 北纬29.39 东经121.24
        浙江省 富阳 北纬30.03 东经119.57
        浙江省 海宁 北纬30.32 东经120.42
        浙江省 湖州 北纬30.52 东经120.06
        浙江省 建德 北纬29.29 东经119.16
        浙江省 江山 北纬28.45 东经118.37
        浙江省 嘉兴 北纬30.46 东经120.45
        浙江省 金华 北纬29.07 东经119.39
        浙江省 兰溪 北纬29.12 东经119.28
        浙江省 临海 北纬28.51 东经121.08
        浙江省 丽水 北纬28.27 东经119.54
        浙江省 龙泉 北纬28.04 东经119.08
        浙江省 宁波 北纬29.52 东经121.33
        浙江省 平湖 北纬30.42 东经121.01
        浙江省 衢州 北纬28.58 东经118.52
        浙江省 瑞安 北纬27.48 东经120.38
        浙江省 上虞 北纬30.01 东经120.52
        浙江省 绍兴 北纬30.00 东经120.34
        浙江省 台州 北纬28.41 东经121.27
        浙江省 桐乡 北纬30.38 东经120.32
        浙江省 温岭 北纬28.22 东经121.21
        浙江省 温州 北纬28.01 东经120.39
        浙江省 萧山 北纬30.09 东经120.16
        浙江省 义乌 北纬29.18 东经120.04
        浙江省 乐清 北纬28.08 东经120.58
        浙江省 余杭 北纬30.26 东经120.18
        浙江省 余姚 北纬30.02 东经121.10
        浙江省 永康 北纬29.54 东经120.01
        浙江省 舟山 北纬30.01 东经122.06
        浙江省 诸暨 北纬29.43 东经120.14
        重庆市 重庆市 北纬29.35 东经106.33
        重庆市 合川市 北纬30.02 东经106.15
        重庆市 江津市 北纬29.18 东经106.16
        重庆市 南川市 北纬29.10 东经107.05
        重庆市 永川市 北纬29.23 东经105.53
    
    

     

    展开全文
  • Python实现经纬度空间点DBSCAN聚类

    万次阅读 多人点赞 2020-09-22 09:33:32
    DBSCAN是一种非常实用的密度聚类算法,而地理空间的经纬度聚类,没有其他维度的信息的话,毫无疑问可以用密度聚类。于是博主重新熟悉了一下算法,并做了一些改进,用Python实现,记录在博客里面。 编译环境:...

    写在前面

    博主前期科研工作中,涉及到要对某个地区的一些空间点进行聚类分析,想到读研期间,曾经用DBSCAN聚类算法实现了四线激光雷达扫描的三维点云数据聚类(论文题目:基于改进DBSCAN算法的激光雷达目标物检测方法),当初用matlab实现的,虽说是改进的算法,但改进方法非常原始。DBSCAN是一种非常实用的密度聚类算法,而地理空间的经纬度点聚类,没有其他维度的信息的话,毫无疑问可以用密度聚类。于是博主重新熟悉了一下算法,并做了一些改进,用Python实现,记录在博客里面。

    • 编译环境:Python3.7
    • 编译器:Spyder 4.1.5

    算法及实现过程

    DBSCAN聚类算法原理

    先简单介绍一下DBSCAN聚类算法的原理:

    DBSCAN(Density-based spatial clustering of applications with noise)是由Martin Ester[8]等人最早提出的一种基于密度的空间聚类算法,该算法将具有足够密度数据的区域划分为k个不同的簇,并能在具有噪声数据的空间域内发现任意形状的簇,本文记为Cj(j=1,2…k),其中簇定义为密度相连点的最大集合,其基本原理是聚类过程要满足以下两个条件:最大性,对于空间中任意两点p、q,如果p属于簇C,并且p密度可达q,则点q也属于簇C;连接性,对于同属于簇的任意两点p、q,它们彼此是密度相连的。DBSCAN算法具有聚类速度快、能有效处理噪声点、能发现空间中任意形状簇、无需划分聚类个数等优点,但DBSCAN聚类算法也有其缺点,其聚类效果高度依赖输入参数——聚类半径和簇内最少样本点数,在高维数据的聚类中,对距离公式选取非常敏感,存在“维数灾难”。

    上面一段引自自己的论文,很不好理解对不对,博主也不打算花精力去解释,因为单独理解这个聚类算法,估计都得写篇博客。想理解原理的,自己在CSDN里面搜,能搜出一大堆博客来,给大家推荐一篇博客,看完基本就明白了。
    DBSCAN聚类算法——机器学习(理论+图解+python代码)
    简单来说,DBSCAN聚类算法需要有数据点,最好是三维以内,高维数据聚类很复杂;需要一个聚类半径,按照核心点搜索半径邻域内的其他点;需要一个聚类最少点数,也就是一个类里面,最少要包含特定数量的点。

    Python实现原始的DBSCAN聚类算法

    DBSCAN聚类算法是机器学习的一种,说到用Python做机器学习,那自然少不了sklearn这个包,这个包里面有cluster方法是专门用来聚类的,而这个聚类函数里面,又有个DBSCAN类,我们来看看这个类吧(为了不影响阅读体验,我建议大家直接跳过不要看,太长了)

    
    # -*- coding: utf-8 -*-
    """
    DBSCAN: Density-Based Spatial Clustering of Applications with Noise
    """
    
    # Author: Robert Layton <robertlayton@gmail.com>
    #         Joel Nothman <joel.nothman@gmail.com>
    #         Lars Buitinck
    #
    # License: BSD 3 clause
    
    import numpy as np
    import warnings
    from scipy import sparse
    
    from ..base import BaseEstimator, ClusterMixin
    from ..utils.validation import _check_sample_weight, _deprecate_positional_args
    from ..neighbors import NearestNeighbors
    
    from ._dbscan_inner import dbscan_inner
    
    
    @_deprecate_positional_args
    def dbscan(X, eps=0.5, *, min_samples=5, metric='minkowski',
               metric_params=None, algorithm='auto', leaf_size=30, p=2,
               sample_weight=None, n_jobs=None):
        """Perform DBSCAN clustering from vector array or distance matrix.
    
        Read more in the :ref:`User Guide <dbscan>`.
    
        Parameters
        ----------
        X : {array-like, sparse (CSR) matrix} of shape (n_samples, n_features) or \
                (n_samples, n_samples)
            A feature array, or array of distances between samples if
            ``metric='precomputed'``.
    
        eps : float, default=0.5
            The maximum distance between two samples for one to be considered
            as in the neighborhood of the other. This is not a maximum bound
            on the distances of points within a cluster. This is the most
            important DBSCAN parameter to choose appropriately for your data set
            and distance function.
    
        min_samples : int, default=5
            The number of samples (or total weight) in a neighborhood for a point
            to be considered as a core point. This includes the point itself.
    
        metric : string, or callable
            The metric to use when calculating distance between instances in a
            feature array. If metric is a string or callable, it must be one of
            the options allowed by :func:`sklearn.metrics.pairwise_distances` for
            its metric parameter.
            If metric is "precomputed", X is assumed to be a distance matrix and
            must be square during fit.
            X may be a :term:`sparse graph <sparse graph>`,
            in which case only "nonzero" elements may be considered neighbors.
    
        metric_params : dict, default=None
            Additional keyword arguments for the metric function.
    
            .. versionadded:: 0.19
    
        algorithm : {'auto', 'ball_tree', 'kd_tree', 'brute'}, default='auto'
            The algorithm to be used by the NearestNeighbors module
            to compute pointwise distances and find nearest neighbors.
            See NearestNeighbors module documentation for details.
    
        leaf_size : int, default=30
            Leaf size passed to BallTree or cKDTree. This can affect the speed
            of the construction and query, as well as the memory required
            to store the tree. The optimal value depends
            on the nature of the problem.
    
        p : float, default=2
            The power of the Minkowski metric to be used to calculate distance
            between points.
    
        sample_weight : array-like of shape (n_samples,), default=None
            Weight of each sample, such that a sample with a weight of at least
            ``min_samples`` is by itself a core sample; a sample with negative
            weight may inhibit its eps-neighbor from being core.
            Note that weights are absolute, and default to 1.
    
        n_jobs : int, default=None
            The number of parallel jobs to run for neighbors search. ``None`` means
            1 unless in a :obj:`joblib.parallel_backend` context. ``-1`` means
            using all processors. See :term:`Glossary <n_jobs>` for more details.
            If precomputed distance are used, parallel execution is not available
            and thus n_jobs will have no effect.
    
        Returns
        -------
        core_samples : ndarray of shape (n_core_samples,)
            Indices of core samples.
    
        labels : ndarray of shape (n_samples,)
            Cluster labels for each point.  Noisy samples are given the label -1.
    
        See also
        --------
        DBSCAN
            An estimator interface for this clustering algorithm.
        OPTICS
            A similar estimator interface clustering at multiple values of eps. Our
            implementation is optimized for memory usage.
    
        Notes
        -----
        For an example, see :ref:`examples/cluster/plot_dbscan.py
        <sphx_glr_auto_examples_cluster_plot_dbscan.py>`.
    
        This implementation bulk-computes all neighborhood queries, which increases
        the memory complexity to O(n.d) where d is the average number of neighbors,
        while original DBSCAN had memory complexity O(n). It may attract a higher
        memory complexity when querying these nearest neighborhoods, depending
        on the ``algorithm``.
    
        One way to avoid the query complexity is to pre-compute sparse
        neighborhoods in chunks using
        :func:`NearestNeighbors.radius_neighbors_graph
        <sklearn.neighbors.NearestNeighbors.radius_neighbors_graph>` with
        ``mode='distance'``, then using ``metric='precomputed'`` here.
    
        Another way to reduce memory and computation time is to remove
        (near-)duplicate points and use ``sample_weight`` instead.
    
        :func:`cluster.optics <sklearn.cluster.optics>` provides a similar
        clustering with lower memory usage.
    
        References
        ----------
        Ester, M., H. P. Kriegel, J. Sander, and X. Xu, "A Density-Based
        Algorithm for Discovering Clusters in Large Spatial Databases with Noise".
        In: Proceedings of the 2nd International Conference on Knowledge Discovery
        and Data Mining, Portland, OR, AAAI Press, pp. 226-231. 1996
    
        Schubert, E., Sander, J., Ester, M., Kriegel, H. P., & Xu, X. (2017).
        DBSCAN revisited, revisited: why and how you should (still) use DBSCAN.
        ACM Transactions on Database Systems (TODS), 42(3), 19.
        """
    
        est = DBSCAN(eps=eps, min_samples=min_samples, metric=metric,
                     metric_params=metric_params, algorithm=algorithm,
                     leaf_size=leaf_size, p=p, n_jobs=n_jobs)
        est.fit(X, sample_weight=sample_weight)
        return est.core_sample_indices_, est.labels_
    
    
    class DBSCAN(ClusterMixin, BaseEstimator):
        """Perform DBSCAN clustering from vector array or distance matrix.
    
        DBSCAN - Density-Based Spatial Clustering of Applications with Noise.
        Finds core samples of high density and expands clusters from them.
        Good for data which contains clusters of similar density.
    
        Read more in the :ref:`User Guide <dbscan>`.
    
        Parameters
        ----------
        eps : float, default=0.5
            The maximum distance between two samples for one to be considered
            as in the neighborhood of the other. This is not a maximum bound
            on the distances of points within a cluster. This is the most
            important DBSCAN parameter to choose appropriately for your data set
            and distance function.
    
        min_samples : int, default=5
            The number of samples (or total weight) in a neighborhood for a point
            to be considered as a core point. This includes the point itself.
    
        metric : string, or callable, default='euclidean'
            The metric to use when calculating distance between instances in a
            feature array. If metric is a string or callable, it must be one of
            the options allowed by :func:`sklearn.metrics.pairwise_distances` for
            its metric parameter.
            If metric is "precomputed", X is assumed to be a distance matrix and
            must be square. X may be a :term:`Glossary <sparse graph>`, in which
            case only "nonzero" elements may be considered neighbors for DBSCAN.
    
            .. versionadded:: 0.17
               metric *precomputed* to accept precomputed sparse matrix.
    
        metric_params : dict, default=None
            Additional keyword arguments for the metric function.
    
            .. versionadded:: 0.19
    
        algorithm : {'auto', 'ball_tree', 'kd_tree', 'brute'}, default='auto'
            The algorithm to be used by the NearestNeighbors module
            to compute pointwise distances and find nearest neighbors.
            See NearestNeighbors module documentation for details.
    
        leaf_size : int, default=30
            Leaf size passed to BallTree or cKDTree. This can affect the speed
            of the construction and query, as well as the memory required
            to store the tree. The optimal value depends
            on the nature of the problem.
    
        p : float, default=None
            The power of the Minkowski metric to be used to calculate distance
            between points.
    
        n_jobs : int, default=None
            The number of parallel jobs to run.
            ``None`` means 1 unless in a :obj:`joblib.parallel_backend` context.
            ``-1`` means using all processors. See :term:`Glossary <n_jobs>`
            for more details.
    
        Attributes
        ----------
        core_sample_indices_ : ndarray of shape (n_core_samples,)
            Indices of core samples.
    
        components_ : ndarray of shape (n_core_samples, n_features)
            Copy of each core sample found by training.
    
        labels_ : ndarray of shape (n_samples)
            Cluster labels for each point in the dataset given to fit().
            Noisy samples are given the label -1.
    
        Examples
        --------
        >>> from sklearn.cluster import DBSCAN
        >>> import numpy as np
        >>> X = np.array([[1, 2], [2, 2], [2, 3],
        ...               [8, 7], [8, 8], [25, 80]])
        >>> clustering = DBSCAN(eps=3, min_samples=2).fit(X)
        >>> clustering.labels_
        array([ 0,  0,  0,  1,  1, -1])
        >>> clustering
        DBSCAN(eps=3, min_samples=2)
    
        See also
        --------
        OPTICS
            A similar clustering at multiple values of eps. Our implementation
            is optimized for memory usage.
    
        Notes
        -----
        For an example, see :ref:`examples/cluster/plot_dbscan.py
        <sphx_glr_auto_examples_cluster_plot_dbscan.py>`.
    
        This implementation bulk-computes all neighborhood queries, which increases
        the memory complexity to O(n.d) where d is the average number of neighbors,
        while original DBSCAN had memory complexity O(n). It may attract a higher
        memory complexity when querying these nearest neighborhoods, depending
        on the ``algorithm``.
    
        One way to avoid the query complexity is to pre-compute sparse
        neighborhoods in chunks using
        :func:`NearestNeighbors.radius_neighbors_graph
        <sklearn.neighbors.NearestNeighbors.radius_neighbors_graph>` with
        ``mode='distance'``, then using ``metric='precomputed'`` here.
    
        Another way to reduce memory and computation time is to remove
        (near-)duplicate points and use ``sample_weight`` instead.
    
        :class:`cluster.OPTICS` provides a similar clustering with lower memory
        usage.
    
        References
        ----------
        Ester, M., H. P. Kriegel, J. Sander, and X. Xu, "A Density-Based
        Algorithm for Discovering Clusters in Large Spatial Databases with Noise".
        In: Proceedings of the 2nd International Conference on Knowledge Discovery
        and Data Mining, Portland, OR, AAAI Press, pp. 226-231. 1996
    
        Schubert, E., Sander, J., Ester, M., Kriegel, H. P., & Xu, X. (2017).
        DBSCAN revisited, revisited: why and how you should (still) use DBSCAN.
        ACM Transactions on Database Systems (TODS), 42(3), 19.
        """
        @_deprecate_positional_args
        def __init__(self, eps=0.5, *, min_samples=5, metric='euclidean',
                     metric_params=None, algorithm='auto', leaf_size=30, p=None,
                     n_jobs=None):
            self.eps = eps
            self.min_samples = min_samples
            self.metric = metric
            self.metric_params = metric_params
            self.algorithm = algorithm
            self.leaf_size = leaf_size
            self.p = p
            self.n_jobs = n_jobs
    
        def fit(self, X, y=None, sample_weight=None):
            """Perform DBSCAN clustering from features, or distance matrix.
    
            Parameters
            ----------
            X : {array-like, sparse matrix} of shape (n_samples, n_features), or \
                (n_samples, n_samples)
                Training instances to cluster, or distances between instances if
                ``metric='precomputed'``. If a sparse matrix is provided, it will
                be converted into a sparse ``csr_matrix``.
    
            sample_weight : array-like of shape (n_samples,), default=None
                Weight of each sample, such that a sample with a weight of at least
                ``min_samples`` is by itself a core sample; a sample with a
                negative weight may inhibit its eps-neighbor from being core.
                Note that weights are absolute, and default to 1.
    
            y : Ignored
                Not used, present here for API consistency by convention.
    
            Returns
            -------
            self
    
            """
            X = self._validate_data(X, accept_sparse='csr')
    
            if not self.eps > 0.0:
                raise ValueError("eps must be positive.")
    
            if sample_weight is not None:
                sample_weight = _check_sample_weight(sample_weight, X)
    
            # Calculate neighborhood for all samples. This leaves the original
            # point in, which needs to be considered later (i.e. point i is in the
            # neighborhood of point i. While True, its useless information)
            if self.metric == 'precomputed' and sparse.issparse(X):
                # set the diagonal to explicit values, as a point is its own
                # neighbor
                with warnings.catch_warnings():
                    warnings.simplefilter('ignore', sparse.SparseEfficiencyWarning)
                    X.setdiag(X.diagonal())  # XXX: modifies X's internals in-place
    
            neighbors_model = NearestNeighbors(
                radius=self.eps, algorithm=self.algorithm,
                leaf_size=self.leaf_size, metric=self.metric,
                metric_params=self.metric_params, p=self.p, n_jobs=self.n_jobs)
            neighbors_model.fit(X)
            # This has worst case O(n^2) memory complexity
            neighborhoods = neighbors_model.radius_neighbors(X,
                                                             return_distance=False)
    
            if sample_weight is None:
                n_neighbors = np.array([len(neighbors)
                                        for neighbors in neighborhoods])
            else:
                n_neighbors = np.array([np.sum(sample_weight[neighbors])
                                        for neighbors in neighborhoods])
    
            # Initially, all samples are noise.
            labels = np.full(X.shape[0], -1, dtype=np.intp)
    
            # A list of all core samples found.
            core_samples = np.asarray(n_neighbors >= self.min_samples,
                                      dtype=np.uint8)
            dbscan_inner(core_samples, neighborhoods, labels)
    
            self.core_sample_indices_ = np.where(core_samples)[0]
            self.labels_ = labels
    
            if len(self.core_sample_indices_):
                # fix for scipy sparse indexing issue
                self.components_ = X[self.core_sample_indices_].copy()
            else:
                # no core samples
                self.components_ = np.empty((0, X.shape[1]))
            return self
    
        def fit_predict(self, X, y=None, sample_weight=None):
            """Perform DBSCAN clustering from features or distance matrix,
            and return cluster labels.
    
            Parameters
            ----------
            X : {array-like, sparse matrix} of shape (n_samples, n_features), or \
                (n_samples, n_samples)
                Training instances to cluster, or distances between instances if
                ``metric='precomputed'``. If a sparse matrix is provided, it will
                be converted into a sparse ``csr_matrix``.
    
            sample_weight : array-like of shape (n_samples,), default=None
                Weight of each sample, such that a sample with a weight of at least
                ``min_samples`` is by itself a core sample; a sample with a
                negative weight may inhibit its eps-neighbor from being core.
                Note that weights are absolute, and default to 1.
    
            y : Ignored
                Not used, present here for API consistency by convention.
    
            Returns
            -------
            labels : ndarray of shape (n_samples,)
                Cluster labels. Noisy samples are given the label -1.
            """
            self.fit(X, sample_weight=sample_weight)
            return self.labels_
    
    

    代码写的很牛逼,但是不建议看,因为我实在是没耐心看完。
    那我们就用这个DBSCAN来写个聚类的示例吧,用鸢尾花数据。
    先看看数据的基本特征:

    import matplotlib.pyplot as plt  
    import numpy as np  
    from sklearn.cluster import KMeans
    from sklearn import datasets 
    from  sklearn.cluster import DBSCAN
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
     
    iris = datasets.load_iris() 
    X = iris.data[:, :4] 
    # 看看数据
    plt.scatter(X[:, 0], X[:, 1], c="red", marker='o', label='see')  
    plt.xlabel('萼片长度')  
    plt.ylabel('萼片宽度')  
    plt.legend(loc=2)  
    plt.show()  
    

    在这里插入图片描述
    这就是基本的数据分布情况,代码很简单,我不再一一解释。
    接下来我们看下最原始的DBSCAN聚类算法,直接看代码:

    dbscan = DBSCAN(eps=0.4, min_samples=9)  # 1
    dbscan.fit(X)   # 2 
    label_pred = dbscan.labels_  # 3
     
    # 绘制聚类结果
    x0 = X[label_pred == 0]  # 4
    x1 = X[label_pred == 1]  # 4
    x2 = X[label_pred == 2]  # 4
    x3 = X[label_pred == -1]   # 4
    plt.scatter(x0[:, 0], x0[:, 1], c="red", marker='o', label='cluster0')  
    plt.scatter(x1[:, 0], x1[:, 1], c="green", marker='*', label='cluster1')  
    plt.scatter(x2[:, 0], x2[:, 1], c="blue", marker='+', label='cluster2') 
    plt.scatter(x3[:, 0], x3[:, 1], c="black", marker='D', label='noise')  
    plt.xlabel('萼片长度')  
    plt.ylabel('萼片宽度')  
    plt.legend(loc=2)  
    plt.show()
    

    我来解释一下我标注的部分:

    1. dbscan = DBSCAN(eps=0.4, min_samples=9) 表示设置参数,聚类半径是0.4,每个类里面的点不少于9个,也就是我前面说的三个参数中的后两个;
    2. dbscan.fit(X) 数据集拟合,机器学习无需多言;
    3. label_pred = dbscan.labels_ 聚类结果,也就是说每个点聚类的情况,如果是-1,说明算法认为这个点是噪声点,我们先来看看聚类结果,如下图(为了方便大家看数据,我把计算得到的label_pred变换了一下,将单列数据变成了6列):
      在这里插入图片描述
      可以看出来,大部分点被归为噪声点,只划分了3个簇,聚类标签分别为0/1/2。
    4. 后面就是根据聚类的标签值,把数据进行分类,并画出来,来看看聚类结果。
      在这里插入图片描述

    好了,原理就介绍这么多,写了这么多相信大家对DBSCAN聚类算法有了一定的理解,那下面进入我们的正题。

    DBSCAN聚类经纬度点

    博主手上有一些经纬度数据点,我想用DBSCAN算法来进行聚类。虽然我前面写了,DBSCAN算法的原始代码不建议看,但是关注源代码里面的这一行代码:

    def __init__(self, eps=0.5, *, min_samples=5, metric='euclidean',
                     metric_params=None, algorithm='auto', leaf_size=30, p=None, n_jobs=None):
    

    其中有一个关键参数,metric=‘euclidean’,意思就是距离计算公式是欧式距离,但是我们的点集是经纬度数据点,如果直接用欧式距离来表达两个点之间的经纬度距离点,会不会有问题呢?
    不管了,先试试看聚类情况。上完整代码

    import pandas as pd
    import numpy as np
    from sklearn.cluster import DBSCAN
    import matplotlib.pyplot as plt
    import seaborn as sns
    import folium
    from sklearn import metrics
    sns.set()
    ## 第一部分
    df = pd.read_csv('00-首页数据.csv')
    df = df[['lat_Amap', 'lng_Amap']].dropna(axis=0,how='all')  
    data = np.array(df)
    
    db = DBSCAN(eps=0.005, min_samples=10).fit(data)
    labels = db.labels_
    raito = len(labels[labels[:] == -1]) / len(labels)  # 计算噪声点个数占总数的比例
    n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)  # 获取分簇的数目
    score = metrics.silhouette_score(data, labels)
     
    df['label'] = labels
    sns.lmplot('lat_Amap', 'lng_Amap', df, hue='label', fit_reg=False)
    
    ## 第二部分
    map_ = folium.Map(location=[31.574729, 120.301663], zoom_start=12,
                           tiles='http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}',
                           attr='default')
    
    colors = ['#DC143C', '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347','#DC143C', 
             '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347', 
             '#DC143C', '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347',
             '#DC143C', '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347','#DC143C', 
             '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347', 
             '#DC143C', '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347','#000000']
    
    for i in range(len(data)):
        folium.CircleMarker(location=[data[i][0], data[i][1]],
                            radius=4, popup='popup',
                            color=colors[labels[i]], fill=True,
                            fill_color=colors[labels[i]]).add_to(map_)
        
    map_.save('all_cluster.html')
    

    代码很长,我们分两部分来看
    第一部分是原始聚类,还有看聚类结果,直接看看sns.lmplot(‘lat_Amap’, ‘lng_Amap’, df, hue=‘label’, fit_reg=False)的效果吧
    在这里插入图片描述
    聚成了40多个类,噪声占比79%。。
    感觉还可以接受啊,但是同学们看懂了的话,肯定会有一个疑问:

    db = DBSCAN(eps=0.005, min_samples=10).fit(data)
    

    这行代码里面,这两个关键参数是怎么获取的?
    比较尴尬,我只能告诉大家,我是一个个试出来,对比原始数据,感觉这个参数最好。

    df['label'] = labels
    

    上面这行代码,是将聚类标签加入到原始数组里面去,看看df
    在这里插入图片描述
    反正有40+类,对于一个市的数据来说,博主觉得研究内容还算合理。
    第二部分在干嘛呢,那是博主在将聚类结果打在地图上,用到了folium这个包,这个包很好用,建议看一下我前一篇博客
    当然,我也是根据聚类的标签来画点的颜色的,因此,我定义了40多个颜色,当然,里面是有重复的颜色,不过不影响视觉效果。为了把每个点都用对应的颜色,我写了个循环,看下面的代码:

    for i in range(len(data)):
        folium.CircleMarker(location=[data[i][0], data[i][1]],
                            radius=4, popup='popup',
                            color=colors[labels[i]], fill=True,
                            fill_color=colors[labels[i]]).add_to(map_)
    

    循环是最简单的方法,看地图上的效果
    在这里插入图片描述
    上图中,黑色的圆圈点是噪声点,其他颜色是不同的类。效果还不错,与实际情况一致,也就是说,用欧式距离是可以的,但是博主一直觉得这样做不妥,在网上搜索了很多资料,终于找到方法替换欧式距离了。

    经纬度实际距离替换欧式距离并进行聚类

    不磨叽,直接上代码

    # -*- coding: utf-8 -*-
    """
    Created on Fri Jun 12 10:39:07 2020
    
    @author: HP
    """
    
    # -*- coding: utf-8 -*-
    """
    Created on Wed May 20 08:32:01 2020
    
    @author: HP
    """
    
    import pandas as pd
    import numpy as np
    from sklearn.cluster import DBSCAN
    import matplotlib.pyplot as plt
    import seaborn as sns
    import folium
    from sklearn import metrics
    from  math import radians
    from math import tan,atan,acos,sin,cos,asin,sqrt
    from scipy.spatial.distance import pdist, squareform
    sns.set()
    
    def haversine(lonlat1, lonlat2):
        lat1, lon1 = lonlat1
        lat2, lon2 = lonlat2
        lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    
        dlon = lon2 - lon1
        dlat = lat2 - lat1
        a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
        c = 2 * asin(sqrt(a))
        r = 6371  # Radius of earth in kilometers. Use 3956 for miles
        return c * r * 1000
    
    
    df = pd.read_csv('00-首页数据.csv')
    
    df = df[['lat_Amap', 'lng_Amap']].dropna(axis=0,how='all')
    # df['lon_lat'] = df.apply(lambda x: [x['lng_Amap'], x['lat_Amap']], axis=1)
    # df = df['lon_lat'].to_frame()
    # data = np.array(data)
    # plt.figure(figsize=(10, 10))
    # plt.scatter(df['lat_Amap'], df['lng_Amap'])
    distance_matrix = squareform(pdist(df, (lambda u, v: haversine(u, v))))
    db = DBSCAN(eps=500, min_samples=10, metric='precomputed').fit_predict(distance_matrix)
    
    
    '''
    db = DBSCAN(eps=0.038, min_samples=3).fit(data)
    '''
    labels = db
    raito = len(labels[labels[:] == -1]) / len(labels)  # 计算噪声点个数占总数的比例
    n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)  # 获取分簇的数目
    # score = metrics.silhouette_score(distance_matrix, labels)
    df['label'] = labels
    sns.lmplot('lat_Amap', 'lng_Amap', df, hue='label', fit_reg=False)
    
    ''' 
    df['label'] = labels
    sns.lmplot('lat_Amap', 'lng_Amap', df, hue='label', fit_reg=False)
    '''
    map_all = folium.Map(location=[31.574729, 120.301663], zoom_start=12,
                         tiles='http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}',
                         attr='default')
    
    # colors = ['#DC143C', '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
    #          '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
    #          '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347', '#000000']
    
    colors = ['#DC143C', '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347','#DC143C', 
             '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347', 
             '#DC143C', '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347',
             '#DC143C', '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347','#DC143C', 
             '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347', 
             '#DC143C', '#FFB6C1', '#DB7093', '#C71585', '#8B008B', '#4B0082', '#7B68EE',
             '#0000FF', '#B0C4DE', '#708090', '#00BFFF', '#5F9EA0', '#00FFFF', '#7FFFAA',
             '#008000', '#FFFF00', '#808000', '#FFD700', '#FFA500', '#FF6347','#000000']
    
    for i in range(len(df)):
        if labels[i] == -1:
            continue
        else :
            folium.CircleMarker(location=[df.iloc[i,0], df.iloc[i,1]],
                                radius=4, popup='popup',
                                color=colors[labels[i]], fill=True,
                                fill_color=colors[labels[i]]).add_to(map_all)
        
    map_all.save('all_cluster.html')
       
    

    敲黑板,我定义的这个函数haversine就是用来求解任意两点之间距离的函数,下面这行代码很关键

    distance_matrix = squareform(pdist(df, (lambda u, v: haversine(u, v))))
    

    计算结果如下,矩阵的意义是任意两点之间的距离,对角线上全为0
    在这里插入图片描述
    再看聚类参数

    db = DBSCAN(eps=500, min_samples=10, metric='precomputed').fit_predict(distance_matrix)
    

    这里的metric='precomputed’不再是欧式距离,后面也不再是fit函数,而是fit_predict函数,用这种方法呢,就将原来的欧式距离换成了实际的距离,当然。看看聚类效果:
    在这里插入图片描述
    由于点太多,我把噪声点去掉了。
    再看看用相同的数据点,我用原始的聚类算发的聚类效果:
    在这里插入图片描述
    我感觉差不多。
    写到这里,其实内容已经写完了。
    但是还有一个问题并没有解决,就是DBSCAN聚类参数,到底该怎么输入,难道真要一个个去试吗,有没有好的办法来解决呢,能不能自适应呢,肯定是可以的。
    继续看下面的内容。

    轮廓系数调整输入参数

    在前面的代码中,一直有一行代码我没解释

    score = metrics.silhouette_score(data, labels)
    

    就是这行代码,从变量的定义来看,我定义了一个得分,metrics.silhouette_score是机器学习中轮廓系数的计算函数,也就是说我可以用这个函数来计算模型的得分,是怎么一个计算过程呢,我这里详细介绍一下:

    在聚类算法中,可以使用轮廓系数(Silhouette Coefficient)对聚类样本的聚类效果进行评估,轮廓系数的计算模型如式(1)、式(2)所示。
    在这里插入图片描述
    上式中, s(i)为样本i的轮廓系数,该值越接近1,说明样本i聚类越合理,越接近-1,说明样本i更应该分类到另外的簇,越接近0,说明样本i在两个簇的边界上; a(i)为样本i到簇内不相似度,为该样本同簇其他样本的平均距离,该值越小,说明该样本越应被聚类到该簇;b(i) 为样本i的簇间不相似度,计算公式如式(3)所示。
    在这里插入图片描述
    式(3)中, bij表示样本i到某簇Cj 所有样本的平均距离。
    根据所有样本的轮廓系数计算平均值,即可得到当前聚类模型的总体轮廓系数值,并依据该值确定输入参数。

    注:以上内容来源于本人论文。
    就是说,我可以根据轮廓系数来不断调整我的输入参数,直到找到轮廓系数最大值对应的输入参数,这样就找到了最佳参数了。
    上流程图
    在这里插入图片描述
    流程图解释的很清楚了,我再上一段代码来解释调参过程。

    res = []
    # 迭代不同的eps值
    for eps in np.arange(0.001,0.13,0.001):
        # 迭代不同的min_samples值
        for min_samples in range(2,11):
            dbscan = DBSCAN(eps = eps, min_samples = min_samples)
            # 模型拟合
            dbscan.fit(data)
            # 统计各参数组合下的聚类个数(-1表示异常点)
            n_clusters = len([i for i in set(dbscan.labels_) if i != -1])
            # 异常点的个数
            outliners = np.sum(np.where(dbscan.labels_ == -1, 1,0))
            # 统计每个簇的样本个数
            # stats = pd.Series([i for i in dbscan.labels_ if i != -1]).value_counts()
            # 计算聚类得分
            try:
                score = metrics.silhouette_score(data, dbscan.labels_)
            except:
                score = -99
            res.append({'eps':eps,'min_samples':min_samples,'n_clusters':n_clusters,'outliners':outliners, 'score':score})
    # 将迭代后的结果存储到数据框中        
    result = pd.DataFrame(res)
    

    相关的参数解释如下:

    1. eps的调参范围是[0.001,0.13],这个参数是根据数据特征来获取的,就是说得对数据有一定的认识才能确定调参范围,循环的步长是0.001,意思就是说,最小距离半径是0.001,最大是0.13,注意,这里用的是欧式距离计算;
    2. min_samples的调参范围是[2,11],一个簇内至少得包含两个点吧,如果最少点超过了11,那么会将所有的点聚成同一个类,参数就是这么定的,循环步长是1。

    这样就完成了整个调参过程。
    实际效果如何和,我只能说不理想。
    我们来看一下,上面我认为聚类较好的参数的轮廓系数:
    在这里插入图片描述
    得分是个负数。。而很多接近于1的轮廓系数对应的聚类效果简直一塌糊涂,不过我尝试了一些其他的数据,总体来说,轮廓系数还是可以来评价的。
    至此,相关技术细节都已介绍完毕。
    不过大家要注意一下,folium包在目前的使用过程中,可能会出现一些问题,我出现的问题就是地图上的标注没法正常显示,可以用下面的方法来解决:
    把folium.py里面原来的http://code.jquery.com/jquery-1.12.4.min.js,替换成https://cdn.bootcdn.net/ajax/libs/jquery/1.12.4/jquery.min.js

    总结

    列一下博客中的技术细节:

    1. DBSCAN聚类算法原理
    2. Python 机器学习实现DBSCAN聚类过程
    3. 应用欧式距离实现聚类
    4. 通过实际计算实际距离得到距离矩阵实现聚类
    5. 聚类结果上地图
    6. 根据轮廓系数调整聚类参数

    这篇博客,总结了博主近半年内研究的东西,涉及到GIS、机器学习,内容比较多。

    注:本文为原创文章,且部分内容涉及知识产权归属,仅供学习讨论,若要引用或转载,请注明本文出处

    展开全文
  • I have a Latitude and Longitude data of size (34000 * 2) in pandas dfdf =Index Latitude Longitude0 66.36031097267725 23.7148073574859361 66.36030099322495 23.7...

    I have a Latitude and Longitude data of size (34000 * 2) in pandas df

    df =

    Index Latitude Longitude

    0 66.36031097267725 23.714807357485936

    1 66.36030099322495 23.71479548193769

    2

    .

    .

    .

    .

    34000 66.27918383581169 23.568631229948359

    Important Note : The above Lat & Long route has been covered twice which means if I cover the route only once, then my Latitude and Longitude data will be of size (34000/2, 2) for example.

    Problem

    I just want Lat and Long Data for a particular selected area. So i filtered using the starting and ending Lat and Long points in my df. On doing that, the another part of the area also selected. (See picture below after filtering)a16d03f0fcec560eee8595671e9182b9.png

    Requirement

    How to remove the additional area ? I am sure there will be some easy approach for this problem.

    Note : The Lat & Long data after filtering also it covered twice.

    Filtered

    def apply_geofence_on_data(interpolated_data, min_latitude=66.27832887852133, max_latitude=66.37098470528755, min_longitude=23.568626549485927,

    max_longitude=23.71481685393929):

    interpolated_data = interpolated_data[interpolated_data['Latitude'] > min_latitude]

    interpolated_data = interpolated_data[interpolated_data['Latitude'] < max_latitude]

    interpolated_data = interpolated_data[interpolated_data['Longitude'] < max_longitude]

    interpolated_data = interpolated_data[interpolated_data['Longitude'] > min_longitude]

    return interpolated_data

    解决方案

    here a solution to test: the idea is to trap all points above the line. you choose the value of P to select the right line.

    aa9d0697fee1e6ea89fb20d988fb014d.png

    from random import uniform

    import matplotlib.pyplot as plt

    def newpoint(lon_min = -180.0, lon_max = 180.0, lat_min = -90.0, lat_max = 90.0 ):#long,lat

    return uniform(lon_min, lon_max), uniform(lat_min, lat_max)

    lon_min = 23.568626549485927; lon_max = 23.71481685393929

    lat_min = 66.27832887852133; lat_max = 66.37098470528755

    p = 0.25 # i have taken this value for sample, for your case i think a value nearer from 0.75

    # i generate 10 points for sample

    n=10

    points = (newpoint(lon_min, lon_max, lat_min, lat_max) for x in range(n))

    points = [x for x in points]

    Lon = [x for x,y in points]

    Lat = [x for y,x in points]

    df = pd.DataFrame({'Lat': Lat, 'Lon': Lon})

    print(df)

    #equation of the line using points A and B -> y=m*x + z

    m = (lat_max - lat_min)/(lon_max - lon_min)

    z = lat_min - m * (lon_min + p * (lon_max - lon_min))

    xa = lon_min + p * (lon_max - lon_min)

    xb = lon_max

    #you could uncomment to display result

    #df['calcul'] = df['Lon'] * m + z

    #select only points above the line

    df = df[df['Lon'] * m + z < df['Lat']]

    print(df)

    #plot to show result

    plt.plot([xa, xb] , [m * xa + z, m * xb + z])

    plt.plot(df.Lon, df.Lat, 'ro')

    plt.show()

    inital ouput:

    Lat Lon

    0 66.343486 23.674008

    1 66.281614 23.678554

    2 66.359215 23.637975

    3 66.303976 23.659128

    4 66.302640 23.589577

    5 66.313877 23.634785

    6 66.309733 23.683281

    7 66.365582 23.667262

    8 66.344611 23.688108

    9 66.352028 23.673376

    e4fd44517cf4d62221d8972a5ba4e4ea.png

    final result: points index 1, 3 and 6 have been put off (they are below the line)

    Lat Lon

    0 66.343486 23.674008

    2 66.359215 23.637975

    4 66.302640 23.589577

    5 66.313877 23.634785

    7 66.365582 23.667262

    8 66.344611 23.688108

    9 66.352028 23.673376

    b20b74bfa5cea71f03ebf4bd4ca230e2.png

    展开全文
  • 基于Hadoop平台的经纬度信息的聚类算法研究与改进.pdf
  • 【K-Means】基于经纬度的城市聚类

    千次阅读 2021-02-06 10:46:56
    K-means聚类算法是一种非层次聚类算法,在最小误差的基础上将数据划分了特定的类,类间利用距离作为相似度指标,两个向量之间的距离越小,其...已知中国部分二级城市的经纬度,要求利用经纬度坐标进行K-Means聚类分析。
  • 我需要用python处理数据量在10万x30天左右的经纬度/时间戳数据。数据都是出租车乘客的下车点,想分析出市区中的一些热点区域。但是目前我的分析遇到了瓶颈,因为以前没有大数据分析的经验,所以目前只是单纯的在用...
  • 用DBSCAN聚类经纬度坐标

    千次阅读 2020-03-26 15:57:53
    用基于密度的聚类算法,计算坐标点聚集地,很好用。 import pandas as pd import numpy as np from sklearn.cluster import DBSCAN from sklearn import metrics import os def dbscan(input_file): columns=['...
  • 说明:第14届认证杯数学建模,用于对经纬度数据点进行区域聚类,此处并将结果可视化显示,大家用得到可以参考一下。 1.Code #!/usr/bin/python # -*-coding:utf-8-*- from initial import * import numpy as np ...
  • An Implementation of DBSCAN on PySpark pyspark的,简单好用,但是改为经纬度坐标后没跑出来。作者对求解过程做了优化,原理是(m+1)ε ≥ d(x, c) ≥ mε then we can filter out points y and z if d(y,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,089
精华内容 435
关键字:

经纬度聚类