0

enter image description hereI am trying to read geodata stored in a CSV file using geopandas and create a map of Europe for college purposes. I extract the geometry values from geopandas DB and add it to my df, though I apparently need to use geojson file. I have spent literally a day going through few tutorials and examples, though I did not manage to link it. If anyone could help, it will be much appreciated. The intention is to add a glyph with a green color to indicate how well each country is doing in Europe based on the mean column.

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
europe = (world.loc[world['continent'] == 'Europe'])
europe.head()

geo_source = GeoJSONDataSource(geojson=europe.to_json())

palette = ['#b9ef96', '#9ae968', '#7be23a', '#6cdf23', '#64dd17']
color_mapper = LogColorMapper(palette=palette)

p = figure(plot_height=600, title='Europe', x_range=(-30,60), y_range= 
(30,85))
p.patches('xs', 'ys', fill_alpha=0.7,
         fill_color='green', line_color='black', line_width=0.5,
         source=geo_source)


show(p)

df_map1 = pd.read_csv('countries_geom.csv', delimiter='\t', index_col=0)
df_map1
df_source = ColumnDataSource(df_map1)

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))
europe = (world.loc[world['continent'] == 'Europe'])
europe.head()

geo_source = GeoJSONDataSource(geojson=europe.to_json())

palette = ['#b9ef96', '#9ae968', '#7be23a', '#6cdf23', '#64dd17']
color_mapper = LogColorMapper(palette=palette)

p = figure(plot_height=600, title='Europe', x_range=(-30,60), y_range= 
(30,85))
p.patches('xs', 'ys', fill_alpha=0.7,
         fill_color='green', line_color='black', line_width=0.5,
         source=geo_source)


    show(p)

df_map1 = pd.read_csv('countries_geom.csv', delimiter='\t', index_col=0)
df_map1
df_source = ColumnDataSource(df_map1)[![df_map_image][1]][1]
Tony
  • 7,767
  • 2
  • 22
  • 51
ReinholdN
  • 526
  • 5
  • 22
  • it would help if you provide a minimal but complete and runnable code with includes and a link to your data – Tony May 08 '19 at 23:06
  • I will do so shortly. Thanks in advance – ReinholdN May 09 '19 at 16:21
  • https://github.com/Reinhold83/GeoMap.git – ReinholdN May 10 '19 at 03:49
  • @Tony https://github.com/Reinhold83/GeoMap.git – ReinholdN May 10 '19 at 03:51
  • Your `Polygon` data as shown in your screenshot and as it really is in your CSV file is incomplete `POLYGON ((3.314971144228537 51.34578095153609,...` I think something went wrong during conversion... ? – Tony May 10 '19 at 14:25
  • @Tony How would you extract it from the dataset? Cause I dont see why it would cut it off half way there – ReinholdN May 10 '19 at 15:43
  • Belgium = europe[(europe.name == 'Belgium')][['geometry']] – ReinholdN May 10 '19 at 15:43
  • Belgium = europe[(europe.name == 'Belgium')]['geometry'] It still gets the same thing – ReinholdN May 10 '19 at 15:44
  • This way works apparently, I need to set array list like adding the , and [ ] all the way which takes the practicability of coding in my view. Any help please? – ReinholdN May 10 '19 at 15:50
  • Belgium = (([3.314971144228537, 51.34578095153609], [4.047071160507528, 51.26725861266857], [4.973991326526914, 51.47502370869813], [5.606975945670001, 51.03729848896978], [6.15665815595878, 50.80372101501058], [6.043073357781111, 50.12805166279423], [5.782417433300907, 50.09032786722122], [5.674051954784829, 49.5294835475575], [4.79922163251581, 49.98537303323639], [4.286022983425084, 49.90749664977255], [3.588184441755686, 50.37899241800358], [3.123251580425801, 50.78036326761458], [2.658422071960274, 50.79684804951575], [2.513573032246143, 51.14850617126183], ... – ReinholdN May 10 '19 at 15:50
  • This looks better. Can you update the CSV file on Github with the full data ? BTW from which database are you extracting this? – Tony May 10 '19 at 16:56
  • The cleaned df is already uploaded there, so you can download it. – ReinholdN May 10 '19 at 20:15
  • The source is from geopandas(gpd) import geopandas as gpd world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) this will give you a gejson format which apparently is very hand compare to other extensions as all you need to do is add the data to the df, but I am having a hard time with it so far. – ReinholdN May 10 '19 at 20:16
  • The CSV file at the location you provided above still contains just one single pair of coordinates like I described in my second post instead of full list of coordinates like you provided above for Belgium. I am not sure if I can help you if we continue this way... – Tony May 13 '19 at 10:52

1 Answers1

2

If you just want to draw the map of Europe then this is the code (for Bokeh v1.1.0):

from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show
from shapely.geometry import Polygon
import geopandas as gp

world = gp.read_file(gp.datasets.get_path('naturalearth_lowres'))
europe = (world.loc[world['continent'] == 'Europe'])
names = [country for country in europe.name]

countries = []
[countries.append(country) if type(item) == Polygon else [countries.append(country) for i in list(item)] for item, country in zip(europe.geometry, names)]

polygons = []
[polygons.append(item) if type(item) == Polygon else [polygons.append(i) for i in list(item)] for item in europe.geometry]

xs, ys = [], []
xs = [list(polygon.boundary.coords.xy[0]) for polygon in polygons]
ys = [list(polygon.boundary.coords.xy[1]) for polygon in polygons]

source = ColumnDataSource(dict(xs = xs, ys = ys, countries = countries))

p = figure(title = 'Europe', tools = 'pan, wheel_zoom, box_zoom, reset, hover, save', tooltips = [('Countries', '@countries')],
           x_range = (-30, 60), y_range = (30, 85), x_axis_location = None, y_axis_location = None)

p.patches('xs', 'ys', fill_alpha = 0.7, fill_color = 'green', line_color = 'black', line_width = 0.5, source = source)
show(p)

enter image description here Result:

Tony
  • 7,767
  • 2
  • 22
  • 51
  • Thanks a lot for your help. I really do appreciate it. – ReinholdN May 13 '19 at 18:55
  • The values that matched with my df and the coords from your code they will work just fine I also can add data to it as you created a CDS which made it easy. I am trying to create a def to extract from a list of str, though it is not working out, can you give me a quick step by step from your code so I can understand it better and stop annoying you, sorry about it I am just learning it at moment. – ReinholdN May 14 '19 at 07:34
  • def countriesN(df, names): country = [c for c in list(names)] countries = [] [countries.append(c) if type(item) == Polygon else [countries.append(c) for i in list(item)] for item, c in zip(df.geometry, names) ] – ReinholdN May 14 '19 at 07:34
  • 1
    I have to say that I'm not an expert so maybe other solutions may be better. Explanation: `europe.geometry` holds the **geodata**. Normally it is a list of `Polygon` objects but when a country, like Russia, has many separate pieces then it is a `Multipolygon` which is a list of `Polygons`. For easy processing I created just one list with Polygons. Then because there were more Polygons than countries I had to repeat some countries (like Russia) so the lists provided to `ColumnDataSource` have equal lengths. – Tony May 14 '19 at 09:26
  • In the `countries` list the country is repeated a number of times equal to number of `Polygons` in `Multipolygon` so that country position in the source list can match the Polygon position in the source. If Russia has 4 shapes (pieces) then the word "Russia" is listed 4x times in the countries list. Is it clear now? – Tony May 14 '19 at 09:28
  • I actually worked it out just before reading your explanation. – ReinholdN May 14 '19 at 11:32
  • After your help I got the grasp how the coodrs work so I can use the geocode from googlemaps to select any country, as some coding is missing in the one we have been working on. I still understanding the overall concepts though how you added the coords to the CDS helped to contextualise it all better. – ReinholdN May 14 '19 at 11:35
  • Great. You can always consider to post here your final code to share with others. – Tony May 14 '19 at 11:41
  • I will indeed. I just posted one now to figure out about the list into string for query. So you can see how your solution was used as a base. https://stackoverflow.com/questions/56129667/pass-list-as-a-string-to-functiongeocode – ReinholdN May 14 '19 at 11:45