CartoDB / cartoframes

CARTO Python package for data scientists
BSD 3-Clause "New" or "Revised" License
251 stars 63 forks source link

ramp color by kmeans clustering result #1524

Open djfan opened 4 years ago

djfan commented 4 years ago

If the distribution of target feature looks like this:

Screen Shot 2020-01-30 at 2 44 01 PM

Commonly, we want to assign colors based on the breaks like this

Screen Shot 2020-01-30 at 2 45 14 PM

There are a few ways to make it happen (e.g. observe the distribution plot -> figure out the percentile of the breaks).

But it would be much much convenient and accurate to apply Kmeans (or other clustering methods) to find the breaks.

Currently, it needs lines of code and some value transformations to make it happen. I hope it could be included as one of the built-in ramp color options as Quantile / EqualInterval / StdDev etc.

cc @andy-esch

djfan commented 4 years ago

For example,

# kmeans for target feature: confirmedCount
color_kmeans = KMeans(n_clusters=7)
data_province['color'] = color_kmeans.fit_predict(data_province['confirmedCount'].values.reshape(-1, 1))

# the kmeans returned cluster numbers are not ordered by target feature values. 
# the following step guarantees 
# feature value of records in cluster 0 > in cluster 1 > 2 > 3 > ...
color_dict = {_: i for i, _ in enumerate(list(data_province.groupby('color').apply(lambda x: x['confirmedCount'].mean()).sort_values().index))}
data_province['color'] = data_province['color'].apply(lambda x: str(color_dict[x]))

# rename the cluster name (0,1,2,3...) as [min, max] of values in each cluster. 
range_dict = data_province.groupby('color').apply(lambda x: str([min(x['confirmedCount']), max(x['confirmedCount'])])).to_dict()
data_province['range'] = data_province['color'].apply(lambda x: range_dict[x])

# the following step makes sure it works well with `color_category_legend` (continuous legend doesn't work as expected)
# the items in legend are in order 
data_province = data_province.sort_values(by='color')
Screen Shot 2020-01-30 at 3 11 05 PM
djfan commented 4 years ago

seems like pygeoda now supports NaturalBreaks

djfan commented 4 years ago

https://github.com/pysal/mapclassify https://pysal.org/mapclassify/

cc @andy-esch