0

I have an empty dictionary which will be in GeoJSON form:

fleet_geojson = {"type": "FeatureCollection", "features": []}

I have a pandas dataframe. Each row is a point in space: latitude, longitude and other information.

df_entire_fleet.to_csv('resources/entire_fleet.csv')

I want to fill the GeoJSON dictionay with the info of each point. Therefore, I do:

df_entire_fleet.apply(
    lambda row: addVehicle2Geojson(fleet_geojson, row['company_id'], row[
        'alarm'], row['battery_level'], row['id'], row['service_area_id'],
                                   row['staff_state'], row['location']),
    axis=1)

Where every string in brackets is the name of a column in the dataframe. The function:

def addVehicle2Geojson(fleet, comp, alarm, batt, id, serv_area, state,
                   coordinates):
fleet['features'].append({
    "type": "Feature",
    "properties": {
        'company_id': comp,
        'alarm': alarm,
        'battery_level': batt,
        'id': id,
        'service_area_id': serv_area,
        'staff_state': state,
    },
    "geometry": {
        "type": "Point",
        "coordinates": coordinates
    }
})

And I get invalid GeoJSON where the order of all the elements is reversed:

{
"features": [
    {
        "geometry": {
            "coordinates": "POINT(-0.00000 0.00000)",
            "type": "Point"
        },
        "properties": {
            "alarm": false,
            "battery_level": 83,
            "company_id": "xxxxxxxx",
            "id": "xxxxxxxx",
            "service_area_id": "xxxxxxxx",
            "staff_state": "xxxxxxxx"
        },
        "type": "Feature"
    },
    {
        "geometry": {
            "coordinates": "POINT(-0.00000 0.00000)",
            "type": "Point"
        },
        "properties": {
            "alarm": false,
            "battery_level": 1,
            "company_id": "xxxxxxxx",
            "id": "xxxxxxxx",
            "service_area_id": "xxxxxxxx",
            "staff_state": "xxxxxxxx"
        },
        "type": "Feature"
    }
],
"type": "FeatureCollection"

}

Why is append() changing the order of the keys?

fbu_94
  • 19
  • 6
  • Even if the order for the same is changed, you will face no problem with accessing any of the fields so I don't think its a case to worry. – JenilDave Jul 29 '20 at 12:37
  • @JenilDave It must be [valid GeoJson](https://geojson.org/) in order to automatically plot the points with any mainstream mapping tool (mapbox, kepler, leaflet etc). – fbu_94 Jul 29 '20 at 12:42
  • [Does the answer here help you?](https://stackoverflow.com/questions/63072680/mongodb-adding-a-new-field-in-an-existing-document-with-specific-position/63085019#63085019) – JenilDave Jul 30 '20 at 07:44

1 Answers1

1

What version of python are you using ?

Starting with python 3.7, the order of the keys in a dictionary is preserved, but before that you have no idea in what order your keys will be the next time you look at them.

Therefore if you really need to preserve the order of the keys, use an OrderedDict, though you probably don't need to to use a geojson :

def addVehicle2Geojson(fleet, comp, alarm, batt, id, serv_area, state, coordinates):
    fleet['features'].append(
        OrderedDict(type="Feature", properties={...}, geometry={...})
    )

Ref: How to keep keys/values in same order as declared?

Ruben Helsloot
  • 12,582
  • 6
  • 26
  • 49
Big Bro
  • 797
  • 3
  • 12
  • I am using python 3.7.6 so dictionaries preserve the order. Thus, the problem can't be with the dictionary. I have tried your proposed solution and printed the OrderedDict. The OrderedDict is correct, but the whole GeoJSON dictionary is still invalid in the same way as posed in the original question. So the problem is most likely with append. I do need to use GeoJSON. – fbu_94 Jul 30 '20 at 05:29
  • Ok, so how do you know that the order is inverted ? Could you provide at least a sample of the original dataframe and the resulting dict ? " I do need to use GeoJSON. " -> Yeah I didn't mean that you don't need GeoJSON, but that _order_ should be unimportant for most GeoJSON applications. – Big Bro Jul 30 '20 at 10:28
  • Order is definitely unimportant. I did not kow that until you and @JenilDave kindly told me, thanks. However, I still do not understand why in python 3.7.6 appending to a dict does not maintain the order as the specification states. – fbu_94 Jul 30 '20 at 10:48
  • Which order are you referring to here ? Because you can't append to a dictionary, the `append` is applied to `fleet['features']` which is a list and should therefore keep the order. A simple way to check is to print all parameters of the `addVehicle2Geojson` method and see if they match the rows of you DataFrame. – Big Bro Jul 30 '20 at 11:08
  • You are right. I meant the list. In the end I used another approach and everything is working fine. I am selecting your answer as a valid solution because it lead me to a working version. OrderedDict is a good solution. – fbu_94 Aug 03 '20 at 06:27