4

I would need some help! By now i used this short code to design a map with folium: pyton_folium_test.txt

The next step for me is to learn how to import positions like this from an excel file, but here i got stuck the last two days. I tried to do the import with pandas, xlrd and also OPENPYXL, but i dont fit to the end. Am i right here to find help for it? can someone help me with that?

Excel below will be an example file to import and the screenshot is how the result should look like. Eingabe_Python.xlsx

enter image description here

#Allgemeine Weltkarte
import pandas as pd
import geopandas
import matplotlib.pyplot as plt

##GPS-Daten und Werte
#Hüttensand-Quellen
q = pd.DataFrame(
    {'City': ['Voestalpine Donawitz'],
     'Amount': [150000],
     'Latitude': [47.37831193777984],
     'Longitude': [15.066798524137285]})

gq = geopandas.GeoDataFrame(
    q, geometry=geopandas.points_from_xy(q.Longitude, q.Latitude))

print(gq.head())



#Hüttensand-Bedarf
b = pd.DataFrame(
    {'City': ['Retznei-Zementwerk', 'Peggau-Zementwerk'],
     'Amount': [ 98741, 78908],
     'Latitude': [ 46.74156539750959, 47.22606763599665],
     'Longitude': [ 15.574118966270278, 15.346740145512106]})

gb = geopandas.GeoDataFrame(
    b, geometry=geopandas.points_from_xy(b.Longitude, b.Latitude))


print(gb.head())

#Plot Österreich Karte mit Punkten
world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))

ax = world[world.name == 'Germany'].plot(
    color='white', edgecolor='black')

gq.plot(ax=ax, color='red', legend=True, legend_kwds={'label':'City'})
gb.plot(ax=ax, color='blue')


plt.show()

#Heatmap
import folium
from folium.plugins import HeatMap

max_amount = float(gb['Amount'].max() and gq['Amount'].max())
print('der maximale Wert ist:',max_amount)


hmap = folium.Map(location=[47.070714, 15.439504], zoom_start=8,control_scale=True )


hm_quellen = HeatMap( data=gq[['Latitude', 'Longitude','Amount']],
                   min_opacity=0.3,
                   max_val=max_amount,
                   gradient = {.3: 'yellow', .6: 'orange', 1: 'red'},
                   radius=20, blur=10,
                   max_zoom=5,

                 )

hmap.add_child(hm_quellen)

hm_bedarf = HeatMap( data=gb[['Latitude', 'Longitude','Amount']],
                   min_opacity=0.3,
                   max_val=max_amount,
                   gradient = {.3: 'turquoise', .6: 'blue',  1: 'grey'},
                   radius=20, blur=15, 
                   max_zoom=1, 
                 )

hmap.add_child(hm_bedarf)

#Markierungen
# Quellen
folium.Marker([47.37831193777984, 15.066798524137285],
              popup=folium.Popup('integrierte Hüttenwerk - Donawitz',show=True)).add_to(hmap)


# Bedarf
folium.Marker([46.74156539750959, 15.574118966270278],
              popup=folium.Popup('Zementwerk - Retznei',show=True)).add_to(hmap)

folium.Marker([47.22606763599665, 15.346740145512106],
              popup=folium.Popup('Zementwerk - Peggau',show=True)).add_to(hmap)



#karte speichern
import os
hmap.save(os.path.join(r'C:\Users\stefa\Desktop\Bachelorarbeit\Daten_Python', 'zement_heatmap.html'))

enter image description here

bose
  • 43
  • 5
  • is there someone who can help a beginner like me? – bose Sep 11 '21 at 15:18
  • Do you have any control over the format of the Excel file? If each town/region (?) eg Quelle, Bedarf were on a separate worksheet and the headers were just Name,Latitude etc then this would make life a lot easier. Then pandas has a very handy read_excel function which will return a dictionary of data frames: https://pandas.pydata.org/docs/reference/api/pandas.read_excel.html It might be worth doing some pre-processing on the Excel data before importing. – DS_London Sep 11 '21 at 15:35
  • Hi, yeah by now i have full control of the excel, just tell me how it should best look like for easy working with it (i am much better in organising excel than in programming). You mean every town on a seperate sheet in the excel? if this will prepare it best, i would try it – bose Sep 12 '21 at 18:29

1 Answers1

1

A possible full solution. I have split out the data acquisition as a separate task from the data display. Since each one of the 'groups' (Quelle, Bedarf etc) has a different colour scheme, I've added a dictionary to hold this information (this could come from a separate configuration file).

Since I don't have GeoPandas (the installation is not simple on Windows), I have commented those lines out: they should work, but I cannot test.

import pandas as pd
#import geopandas
#import matplotlib.pyplot as plt
import folium
from folium.plugins import HeatMap

def LoadData(filename):
    #Read in 1st sheet of Excel file
    dfLocations = pd.read_excel(filename)

    GroupData = {}
    fields = []
    max_amount = 0.0

    #Run through the column headers
    #to extract all the unique field names and groups
    for hdr in dfLocations.columns:
        parts = hdr.split('_')
        if( len(parts) ) > 1: #column names not in Field_Group format
            if( parts[0] not in fields ):
                fields.append(parts[0])
            GroupData[parts[1]]=None

    #Now parse the data, group by group
    for r in GroupData:
        df = dfLocations[[ fld + '_' + r for fld in fields]].dropna().set_axis(fields, axis=1, inplace=False)
        df.rename(columns={'Name':'City'},inplace=True)
        max_amount = max(max_amount,df.Amount.max())
        GroupData[r] = df

    return GroupData,max_amount

dictGroups,max_amount = LoadData('ImportFile.xlsx')

#Set up colour schemes for plot, markers and heatmaps
#NB: need one line for every different group
colourScheme = [{'loc': 'red','heatmap': {.3: 'yellow', .6: 'orange', 1: 'red'},'radius':20,'blur':10 },
                {'loc': 'blue','heatmap': {.3: 'turquoise', .6: 'blue',  1: 'grey'},'radius':20,'blur':15}]

if len(colourScheme) < len(dictGroups):
    raise ValueError('Insufficient Colour Scheme entries for the number of Groups')
    
#world = geopandas.read_file(geopandas.datasets.get_path('naturalearth_lowres'))
#ax = world[world.name == 'Germany'].plot(color='white', edgecolor='black')

hmap = folium.Map(location=[47.070714, 15.439504], zoom_start=8,control_scale=True )

nGroup = 0
for r in dictGroups:
    dfLocations = dictGroups[r]
    scheme = colourScheme[nGroup]

    #gdf = geopandas.GeoDataFrame(dfLocations, geometry=geopandas.points_from_xy(dfLocations.Longitude, dfLocations.Latitude))
    #gdf.plot(ax=ax,color=scheme['loc'],legend=True,legend_kwds={'label':'City'})

    hmap.add_child(HeatMap( data=dfLocations[['Latitude', 'Longitude','Amount']],
                            min_opacity=0.3,
                            max_val=max_amount,
                            gradient = scheme['heatmap'],
                            radius=scheme['radius'], blur=scheme['blur'],
                            max_zoom=5 ) )

    for idx,location in dfLocations.iterrows():
        folium.Marker([location.Latitude,location.Longitude],
                      popup = folium.Popup(location.City,show=True)).add_to(hmap)
    nGroup += 1

#plt.show()
hmap.save('zement_heatmap.html')
DS_London
  • 3,644
  • 1
  • 7
  • 24
  • wow this looks really helpfull, thanks! if i have my code so far, how can i easily use this result to fit it into code somehow like i did previously to plot my map like the example? – bose Sep 12 '21 at 18:32
  • @bose I don't have the geopandas package so can't test that part. Take some time to look through the code I've posted, and understand how it works. That will give you the insight on how to use the imported DataFrame. – DS_London Sep 13 '21 at 09:48
  • @bose I've posted a fuller answer – DS_London Sep 13 '21 at 11:30
  • oh thank u a lot, this looks so great, you helped me a lot. i will try it and if i still have problems i will contact you again but thankyou very much ba now – bose Sep 14 '21 at 15:47
  • wow thank you very much, it worked perfectly!! so by now this is all i need, if i get some more stuff i need to display i will maybe ask you again for help, if itis okay? @DS_London ps: sorry btw for my maybe not so good english – bose Sep 14 '21 at 16:05
  • 1
    @bose No worries. SO is not a coding service though: perhaps take some time to understand how the code works and you may not need more help! – DS_London Sep 14 '21 at 16:28
  • yeah i know, i try my best for future issues, i would not have come here if i did not see myself lost after few days of trying to solve it myself :O – bose Sep 15 '21 at 17:29