7

I have a map of Chile (http://labgeo.ufro.cl/fichas/chile_geo/ficha_cl_geo.html first link that says "Chile continental) and would like to plot it and add some points of centers for which I have latitude and longitud data.

I am newbie with geopandas and matplotlib but I managed to plot the map with the centers as dots of different colors using the suggested answer for matplotlib from this post: Color by Column Values in Matplotlib

Here is my code:

#Loading data, since I am making the coordinates up they won´t fit the map nicely but you will get the idea

map_= gpd.read_file("cl_continental_geo.shp")
geo_df_ = pd.DataFrame({"id":np.random.randint(20, size=133) ,"Latitude": np.random.normal(-34.406922,7.819504, 133), "Longitud": np.random.normal(-71.243350,1.254126, 133)})

geometry =[Point(xy) for xy in zip( geo_df_["Longitud"],geo_df_["Latitude"])]
geo_df_ =gpd.GeoDataFrame(geo_df_, crs={"init":"epsg:4326"},geometry= geometry)

# creating color map for categories
categories = np.unique(geo_df_["id"])
colors = np.linspace(0, 1, len(categories))
colordict = dict(zip(categories, colors))

#matching it to the geopandas df
geo_df_["Color"] = geo_df_["id"].apply(lambda x: colordict[x])

#plotting    
geo_df_.plot(ax=map_.plot(figsize=(40, 30)), marker='o', c =geo_df_.Color, markersize=100)

What I can´t make trying different things is the legend to appear.

  • I have tried adding legend=True
  • I have tried doing it through defining ax first but I can´t manage to feed the data correctly to create the plot and end up with nothing.
  • Tried this solution but my shp file has only one row with multipolygon info and I don´t know how to create the crossed dataframe proposed Generating Legend for geopandas plot

So far the only thing I have managed to do is showing the dictionary of the ids with the color number by adding .legend() at the end as this: geo_df_.plot(ax=map_.plot(figsize=(40, 30)), marker='o', c =geo_df_.Color, markersize=100).legend() . But I get this error

No handles with labels found to put in legend.

but when I pass the color dictionary as an argument it would show one point in the legend.

What I would like to achieve is a legend as this:

enter image description here

taken from this post: Control ggplot2 legend look without affecting the plot My ideal legend would be to have a square on the side with all the colored dots identified with the id center that they represent. So for example yellow dot: (center) 5, purple dot : 8, etc.

What I have manages is just one dot, that shows the entire dictionary as this:

example of part of the map with the dictionary legend

Isa
  • 93
  • 1
  • 1
  • 7
  • What happens if you add `plt.legend()` at the end of your code? – Juan C Oct 15 '19 at 14:38
  • It gives the No handles with labels. If I add label =geo_df_.Color inside the plot function and then add plt.legend() it prints the color dictionary of the ids with the number of the color. – Isa Oct 15 '19 at 14:57
  • and `label=categories` ? – Juan C Oct 15 '19 at 15:00
  • then it gives me one point of color and a list of the category. It prints the legend but not with all the color points nor the mapping. – Isa Oct 15 '19 at 15:01
  • Could you add a picture to your question to have a better grasp of the problem? – Juan C Oct 15 '19 at 15:03
  • I thought I didn´t have the privilege to upload images. In the picture you can see a part of the map and the centers as dots, and in the right you can see the legend which has only one dot and the whole dictionary info. I either get that or the same dot with some integer. – Isa Oct 15 '19 at 15:11
  • And how would your ideal legend look like? – Juan C Oct 15 '19 at 17:17
  • added to the end of the question – Isa Oct 15 '19 at 19:48

1 Answers1

9

Do not use c, but column. And then legend=True will do the trick to show the legend and categorical=True will give you what you want. In this specific case you might run out of colors, so you will have to set another colormap if you want all colors different (cmap='')

map_= gpd.read_file("/Users/martin/Downloads/cl_continental_geo/cl_continental_geo.shp")
geo_df_ = pd.DataFrame({"id":np.random.randint(20, size=133) ,"Latitude": np.random.normal(-34.406922,7.819504, 133), "Longitud": np.random.normal(-71.243350,1.254126, 133)})

geometry =[Point(xy) for xy in zip( geo_df_["Longitud"],geo_df_["Latitude"])]
geo_df_ =gpd.GeoDataFrame(geo_df_, crs={"init":"epsg:4326"},geometry= geometry)

#plotting    
ax = map_.plot(figsize=(40, 30))
geo_df_.plot(ax=ax, marker='o', column='id', categorical=True,
             markersize=100, legend=True, cmap='tab20')

enter image description here

philipnye
  • 352
  • 1
  • 3
  • 16
martinfleis
  • 7,124
  • 2
  • 22
  • 30
  • Hey thank you for taking the time. Thing is the value in color dict doesn´t represent a cuantitative measure, they are numbers I generated following another post to give colors to each unique center id. What I need is a legend that lets me visualize where is a specific center located in the map. So I need a map between the code of the center and the color of the dot. Not a color bar – Isa Oct 15 '19 at 19:08
  • I don't think I understand. Having the data you linked and a snippet above, which column stores the value you want to plot? I would like to help, but I have no idea what are you trying to achieve. – martinfleis Oct 15 '19 at 21:24
  • What I want to plot are the locations of centers in the map of Chile. The colors would indicate the id of the centers. I edited my question in the end adding an example of what I would like to obtain. – Isa Oct 16 '19 at 02:45
  • `geo_df_.plot(ax=ax, marker='o', column='id', categorical=True, markersize=100, legend=True)` ?? – martinfleis Oct 16 '19 at 06:58
  • that was it! only thing is the colors repeat in the legend so for every three centers it uses the same color. Can you please update your question with this line so I can accept your answer. Thank you – Isa Oct 16 '19 at 19:30
  • Edited with a brief explanation of repeating colours. – martinfleis Oct 16 '19 at 21:31