8

I have this working code, data2kml() function works ok, but data2geojson() is incomplete. How can I add the elevation, name and the description in the GeoJSON? I can't understand how FeatureCollection works.

Obs: I can't use GeoPandas because of some dependency conflicts.

import json
import geojson
import simplekml
import pandas as pd
def data2kml(df):
 kml = simplekml.Kml()
 df.apply(lambda X: kml.newpoint(
 name=X["name"], 
 description=unicode(X["description"].decode('utf8')), 
 coords=[( X["long"], X["lat"], X["elev"])]
 )
 , axis=1)
 kml.save(path='map.kml')
def data2geojson(df):
 points = []
 df.apply(lambda X: points.append( (float(X["long"]), 
 float(X["lat"]))
 )
 , axis=1)
 with open('map.geojson', 'w') as fp:
 geojson.dump(geojson.MultiPoint(points), fp, sort_keys=True)
col = ['lat','long','elev','name','description']
data = [[-29.9953,-70.5867,760,'A','Place a'],
 [-30.1217,-70.4933,1250,'B','Place b'],
 [-30.0953,-70.5008,1185,'C','Place c']]
df = pd.DataFrame(data, columns=col)
data2kml(df)
data2geojson(df)
Taras
35.7k5 gold badges77 silver badges151 bronze badges
asked Dec 11, 2016 at 1:13

4 Answers 4

11

Using what i learned from the answer of @gene this solution avoids the use of iterrows because iterrows have performance issues.

Valid for Python 3.X

import pandas as pd
import geojson
def data2geojson(df):
 features = []
 insert_features = lambda X: features.append(
 geojson.Feature(geometry=geojson.Point((X["long"],
 X["lat"],
 X["elev"])),
 properties=dict(name=X["name"],
 description=X["description"])))
 df.apply(insert_features, axis=1)
 with open('map1.geojson', 'w', encoding='utf8') as fp:
 geojson.dump(geojson.FeatureCollection(features), fp, sort_keys=True, ensure_ascii=False)
col = ['lat','long','elev','name','description']
data = [[-29.9953,-70.5867,760,'A','Place ñ'],
 [-30.1217,-70.4933,1250,'B','Place b'],
 [-30.0953,-70.5008,1185,'C','Place c']]
df = pd.DataFrame(data, columns=col)
data2geojson(df)

Valid for Python 2.X

import pandas as pd
import geojson
def data2geojson(df):
 features = []
 df.apply(lambda X: features.append( 
 geojson.Feature(geometry=geojson.Point((X["long"], 
 X["lat"], 
 X["elev"])), 
 properties=dict(name=X["name"], 
 description=unicode(X["description"].decode('utf8'))))
 )
 , axis=1)
 with open('map.geojson', 'w') as fp:
 geojson.dump(geojson.FeatureCollection(features), fp, sort_keys=True)
col = ['lat','long','elev','name','description']
data = [[-29.9953,-70.5867,760,'A','Place a'],
 [-30.1217,-70.4933,1250,'B','Place b'],
 [-30.0953,-70.5008,1185,'C','Place c']]
df = pd.DataFrame(data, columns=col)
data2geojson(df)
answered Dec 11, 2016 at 21:54
3

Geoff Boeing provides a solution in Exporting Python Data to GeoJSON and Convert a pandas dataframe to geojson for web-mapping (Jupyter notebook) for 2D coordinates and you can adapt his script for 3D coordinates

def df_to_geojson(df, properties, lat='lat', lon='long', z='elev'):
 geojson = {'type':'FeatureCollection', 'features':[]}
 for _, row in df.iterrows():
 feature = {'type':'Feature',
 'properties':{},
 'geometry':{'type':'Point','coordinates':[]}}
 feature['geometry']['coordinates'] = [row[lon],row[lat],row[z]]
 for prop in properties:
 feature['properties'][prop] = row[prop]
 geojson['features'].append(feature)
 return geojson
cols = ['name', 'description']
df_to_geojson(df, cols)
{'type': 'FeatureCollection', 'features': [{'geometry': {'type': 'Point', 'coordinates': [-70.5867, -29.9953, 760]}, 'type': 'Feature', 'properties': {'name': 'A', 'description': 'Place a'}}, {'geometry': {'type': 'Point', 'coordinates': [-70.4933, -30.1217, 1250]}, 'type': 'Feature', 'properties': {'name': 'B', 'description': 'Place b'}}, {'geometry': {'type': 'Point', 'coordinates': [-70.5008, -30.0953, 1185]}, 'type': 'Feature', 'properties': {'name': 'C', 'description': 'Place c'}}]}

To explain the process with single features

for i, row in df.iterrows():
 print i,
 feature = {'type':'Feature','properties':{},'geometry':{'type':'Point','coordinates':[]}}
 feature['geometry']['coordinates'] = [row.long,row.lat,row.elev]
 for prop in cols:
 feature['properties'][prop] = row[prop]
 print feature
0 {'geometry': {'type': 'Point', 'coordinates': [-70.5867, -29.9953, 760]}, 'type': 'Feature', 'properties': {'name': 'A', 'description': 'Place a'}}
1 {'geometry': {'type': 'Point', 'coordinates': [-70.4933, -30.1217, 1250]}, 'type': 'Feature', 'properties': {'name': 'B', 'description': 'Place b'}}
2 {'geometry': {'type': 'Point', 'coordinates': [-70.5008, -30.0953, 1185]}, 'type': 'Feature', 'properties': {'name': 'C', 'description': 'Place c'}}
answered Dec 11, 2016 at 9:18
1
  • Thanks for the answer, I finally learned the internal structure of the geojson format. With this knowledge i'm going to publish a solution that avoid the use of iterrows because this. Commented Dec 11, 2016 at 21:48
2

For Python 3.6 users, this works for me:

where df = yourdataframe, properties are the usefull_columns, lat='latitude', lng='longitude'

The usefull_columns come from the original dataframe

I've added some testing points

# create the function
def df_to_geojson(df, properties, lat='latitude', lng='longitude'):
 """
 Turn a dataframe containing point data into a geojson formatted python dictionary
 df : the dataframe to convert to geojson
 properties : a list of columns in the dataframe to turn into geojson feature properties
 lat : the name of the column in the dataframe that contains latitude data
 lng : the name of the column in the dataframe that contains longitude data
 """
 # create a new python dict to contain our geojson data, using geojson format
 geojson = {'type':'FeatureCollection', 'features':[]}
 # loop through each row in the dataframe and convert each row to geojson format
 # x is the equivalent of the row, df.iterrows converts the dataframe in to a pd.series object
 # the x is a counter and has no influence
 for x, row in df.iterrows():
 feature = {'type':'Feature',
 'properties':{},
 'geometry':{'type':'Point',
 'coordinates':[]}}
 # fill in the coordinates
 feature['geometry']['coordinates'] = [float(row.lng),float(row.lat)]
 # be aware that the dataframe is a pd.series
 #print('rowitem converts to ndarray(numpy) :\n ', row)
 # convert the array to a pandas.serie
 geo_props = pd.Series(row)
 # for each column, get the value and add it as a new feature property
 # prop determines the list from the properties
 for prop in properties:
 #loop over the items to convert to string elements
 #convert to string
 if type(geo_props[prop]) == float:
 #print('ok')
 geo_props[prop] = str(int(geo_props[prop]))
 # now create a json format, here we have to make the dict properties
 feature['properties'][prop] = geo_props[prop]
 # add this feature (aka, converted dataframe row) to the list of features inside our dict
 geojson['features'].append(feature)
 return geojson
jrovegno
2931 gold badge2 silver badges9 bronze badges
answered Jan 1, 2018 at 12:58
1
  • 1
    Please remember to indent your code so it is formatted correctly. The {} button does this for you. Commented Jan 1, 2018 at 14:05
0

I have used this code:

def return_geojson(df, latlng):
 d = dict(type="FeatureCollection",features=[])
 for ind,row in df.fillna('').iterrows():
 p = row.drop(latlng).to_dict()
 g = dict(type="Point",coordinates=list(row[latlng])[::-1])
 f = dict(type="Feature", properties=p, geometry=g)
 d['features'].append(f)
 return d
with open('map.geojson','w') as f:
 json.dump(return_geojson(df,['lat','lon']),f)
answered Feb 18, 2018 at 19:38

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.