I'm trying to cluster points based on the sum of a attributes of its nearest neighbors. So here are the points in the data set as they are:base point lists

The objective is that each point has an "evalfield" attribute associated with it. I want to be able to cluster them such that the sum of the clustered points ad up to a predetermined value that I decide.(last column).

The attribute table

To illustrate with an example: Here are a collection of points , with their attribute on the basis for which clustering is too occur written above them. (0.5,0.6 etc.)

I want to be able to cluster them such that the sum of this value in a cluster adds up to a predetermined value (1.1 in this case) End objective


So I followed the steps and pretty much copied out the code as is to run it in qgis.

import geopandas as gpd
from shapely import geometry as geom

gdf = gpd.read_file('filteredptlst.shp')
exploded_gdf = gpd.GeoDataFrame()
exploded_gdf.crs = gdf.crs

print('starting ...')

for index, row in gdf.iterrows():
    if float(row['evalfield']) == 0.01:
        exploded_gdf = exploded_gdf.append(row, ignore_index=True)
        for i in range(0, int(row['evalfield']*100)):
            entry = row.copy()
            entry['evalfield'] = 0.01
            exploded_gdf = exploded_gdf.append(entry, ignore_index=True)

print('processing done ... saving')

gdf.to_file(driver='ESRI Shapefile', filename="result.shp")


But I keep getting this error:

Python Console 
Use iface to access QGIS API interface or Type help(iface) for more info
execfile(u'C:/Users/USER/OneDrive/Documents/Studies etc/adrchitectural design/thesis/Thesisgisdata/Siteselectionalgs/alg1_point_filtering_explosion.py'.encode('mbcs'))
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "C:/Users/USER/OneDrive/Documents/Studies etc/adrchitectural design/thesis/Thesisgisdata/Siteselectionalgs/alg1_point_filtering_explosion.py", line 24, in <module>
    gdf = gpd.read_file('filteredptlst.shp')
  File "C:\PROGRA~1\QGIS2~1.18\apps\Python27\lib\site-packages\geopandas\io\file.py", line 19, in read_file
    with fiona.open(filename, **kwargs) as f:
  File "C:\PROGRA~1\QGIS2~1.18\apps\Python27\lib\site-packages\fiona\__init__.py", line 170, in open
    raise IOError("no such file or directory: %r" % path)
IOError: no such file or directory: 'filteredptlst.shp'

Ive already tried changing the project environment and putting in a complete file path to the location of the file.

I couldn't se anything wrong with the code so I ran it separately in Visual Studio , but that doesn't seem to work either , there are no trackback errors but none of the print messages which I put I ( to check) arent't displayed either.

P.S. I'm really new to both GIS and Python and there must be something really obvious I'm overlooking here.

1 Answer 1


NOTE : I'm using here some packages that you didn't mention in your tags

My suggestion would be to first explode your points data to the unit (like 0.1), this means a point that have a value of 0.5 will generate five points each have a value of 0.1

EDIT : to explode your points you can loop through your dataset and create new points when your value isn't equal to 0.1

import geopandas as gpd
from shapely import geometry as geom

gdf = gpd.read_file('your_points.shp')
exploded_gdf = gpd.GeoDataFrame()
exploded_gdf.crs = gdf.crs 
for index, row in gdf.iterrows():
    if row['your_value'] == 0.1:
        exploded_gdf = exploded_gdf.append(row, ignore_index = True)
        for i in range(0, row['your_value']*10):
             entry = row.copy()
             entry['your_value'] = 0.1
             exploded_gdf = exploded_gdf.append(entry, ignore_index = True)

here take a look at this you'll like it geopandas

then run K-means clustering algorithm from scipy package to cluster your points:

from scipy.cluster.vq import kmeans2, whiten
import geopandas as gpd
import numpy as np

gdf = gpd.read_file('your_exploded_points.shp')
coordinates = np.array(list(gdf['geometry'].apply(lambda x: list(x.coords[0]))))
x, y = kmeans2(whiten(coordinates), int(math.ceil(len(coordinates)/your_value_of_cluster*10)) , iter = 10, minit = 'points')
# you can tune the parameter iter to get the best results
  • 1
    I'm open to solving this in some other way. Kinda a newbie here , how do I go about exploding the point data like you said?
    – user111752
    Jan 15, 2018 at 10:24
  • @rangeet I've edited my answer to explode your points Jan 15, 2018 at 10:47
  • So I think I need a little help with the python console, I realize that I'm straying from the original question but I might as well finish up on all my problems here
    – user111752
    Jan 15, 2018 at 20:41
  • @rangeet the error you are getting is because of a wrong path of the shapefile provided, you'll have to specify the correct path of the shapefile instead of just the name in gpd.read_file(...) Jan 17, 2018 at 8:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.