6

I have this working code, data2kml 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 simplekml
import geojson
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)
6

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)
2

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'}}
  • 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. – jrovegno Dec 11 '16 at 21:48
1

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
  • 1
    Please remember to indent your code so it is formatted correctly. The {} button does this for you. – Vince Jan 1 '18 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)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.