I have geojson file as follows:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
57.45849609375,
57.36801461845934
],
[
57.10693359375,
56.31044317134597
],
[
59.205322265625,
56.20059291588374
],
[
59.4140625,
57.29091812634045
],
[
57.55737304687501,
57.36801461845934
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[
59.40307617187499,
57.29685437021898
],
[
60.8203125,
57.314657355733274
],
[
60.74340820312499,
56.26776108757582
],
[
59.227294921875,
56.21281407174654
],
[
59.447021484375,
57.29091812634045
]
]
}
}
]
}
I want to replace LineString in "type": "LineString" with Polygon, and also, replace coordinates last point of each linestring by coordinates of first point to make it close if it has more than 3 points.
How can I do it in Python with geopandas or pandas? Thanks.
Here is expected output:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
57.45849609375,
57.36801461845934
],
[
57.10693359375,
56.31044317134597
],
[
59.205322265625,
56.20059291588374
],
[
59.4140625,
57.29091812634045
],
[
57.45849609375,
57.36801461845934
]
]
}
},
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
59.40307617187499,
57.29685437021898
],
[
60.8203125,
57.314657355733274
],
[
60.74340820312499,
56.26776108757582
],
[
59.227294921875,
56.21281407174654
],
[
59.40307617187499,
57.29685437021898
]
]
}
}
]
}
Script to get type and coordinates of first LineString:
import json
from pprint import pprint
with open('data.geojson') as f:
data = json.load(f)
pprint(data)
data["features"][0]["geometry"]['type']
data["features"][0]["geometry"]['coordinates']
You can achieve that with the json module:
file_line = 'file.json'
file_poly = 'file_poly.json'
import json
with open(file_line, 'r') as f:
data = json.load(f)
for feature in data['features']:
if (feature['geometry']['type'] == 'LineString') & (len(feature['geometry']['coordinates']) >= 3):
feature['geometry']['type'] = 'Polygon'
feature['geometry']['coordinates'].append(feature['geometry']['coordinates'][0])
with open(file_poly, 'w+') as f:
json.dump(data, f, indent=2)
Related
Is there any way to convert a pandas dataframe into a json with different levels, I have this dataframe:
df = pd.DataFrame([
{"type":"Feature","Id":319,"Departament":"1 DE MAYO","State":"CHACO","coordinates":[[[-58.95370956800002, -26.87059472200002]]]},
{"type":"Feature","Id":320,"Departament":"12 DE OCTUBRE","State":"CHACO","coordinates":[[[-58.95370956800002, -26.87059472200002]]]},
{"type":"Feature","Id":314,"Departament":"2 DE ABRIL","State":"CHACO","coordinates":[[[-58.95370956800002, -26.87059472200002]]]},
{"type":"Feature","Id":308,"Departament":"25 DE MAYO","State":"CHACO","coordinates":[[[-58.95370956800002, -26.87059472200002]]]},
{"type":"Feature","Id":100,"Departament":"25 DE MAYO","State":"CHACO","coordinates":[[[-58.95370956800002, -26.87059472200002]]]}])
I really want an output like so:
"features": [
{
"type": "Feature",
"properties": {
"id": 319,
"Departament": "1 DE MAYO",
"State": "CHACO"
},
"geometry": {
"coordinates": [
[
[
-58.32487869300002,
-30.838373183999977
]
]
]
}
}
]
}
Thanks for your help i hope i was clear.
You can use:
import json
def to_json(row):
return {'type': row.iloc[0],
'properties': row.iloc[1:-1].to_dict(),
'geometry': row.iloc[-1]}
data = {'features': df.apply(to_json, axis=1).to_list()}
print(json.dumps(data, indent=2))
Output:
{
"features": [
{
"type": "Feature",
"properties": {
"Id": 319,
"Departament": "1 DE MAYO",
"State": "CHACO"
},
"geometry": [
[
[
-58.95370956800002,
-26.87059472200002
]
]
]
},
{
"type": "Feature",
"properties": {
"Id": 320,
"Departament": "12 DE OCTUBRE",
"State": "CHACO"
},
"geometry": [
[
[
-58.95370956800002,
-26.87059472200002
]
]
]
},
{
"type": "Feature",
"properties": {
"Id": 314,
"Departament": "2 DE ABRIL",
"State": "CHACO"
},
"geometry": [
[
[
-58.95370956800002,
-26.87059472200002
]
]
]
},
{
"type": "Feature",
"properties": {
"Id": 308,
"Departament": "25 DE MAYO",
"State": "CHACO"
},
"geometry": [
[
[
-58.95370956800002,
-26.87059472200002
]
]
]
},
{
"type": "Feature",
"properties": {
"Id": 100,
"Departament": "25 DE MAYO",
"State": "CHACO"
},
"geometry": [
[
[
-58.95370956800002,
-26.87059472200002
]
]
]
}
]
}
You can use the dataframes’ .to_json() method.
I'm actually learning how to do some cartography with python but first I would like to convert my json file to a GeoJson dynamically with Python. This is how my Json looks like :
[
{
"shape_name": "unit_shape",
"source_name": "7724C_BUSSY_SAINT_GEORGES_Bussycomore",
"building_id": "7724C",
"chaud_froid": "Chaud",
"geojson": {
"type": "LineString",
"properties": {
"densite_cc": null
},
"coordinates": [
[
2.726142,
48.834359
],
[
2.726149,
48.834367
],
[
2.726202,
48.834422
],
[
2.726262,
48.834429
],
[
2.726307,
48.834434
],
[
2.726316,
48.834435
]
]
},
"to_drop": null,
"id_enquete": null,
"shape_nom": null
},
...(many other features similar to the precedent one)]
Can someone please help me ?
import json
input_file=json.load(open("./data/data.json", "r", encoding="utf-8"))
geojs={
"type": "FeatureCollection",
"features":[
{
"type":"Feature",
"geometry": {
"type":"LineString",
"coordinates":d["geojson"]["coordinates"],
},
"properties":d,
} for d in input_file
]
}
output_file=open("./data/geodata.json", "w", encoding="utf-8")
json.dump(geojs, output_file)
output_file.close()
i would like to know why the below posted geojson format is invalid. i tried to visualize its data in
http://geojson.io
but nothing gets displayed.
geojson
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[[7.85563468082516,49.90287230375267],[7.855636808249913,49.902782379662085],[7.855776033932631,49.902783753651605],[7.855773906766568,49.902873677746555]]
]
]
},"properties": {"areaOfCoverage":"30"}},
}
Try this:
{
"type": "FeatureCollection",
"features": [
{
"properties":{"areaOfCoverage":"30"},
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
7.85563468082516,
49.90287230375267
],
[
7.855636808249913,
49.902782379662085
],
[
7.855776033932631,
49.902783753651605
],
[
7.85563468082516,
49.90287230375267
]
]
]
}
}
]
}
I'd like to serialize GeoJSON FeatureCollections in Python with limited precision for their coordinates.
For example, here's a FeatureCollection (represented as dicts and lists in Python):
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "Liberty Island",
"area_sqm": 24950.40123456,
"established": 1875,
"height_ft": 305
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[ -74.04715418815613, 40.690994683044906 ],
[ -74.04499769210815, 40.68873311507798 ],
[ -74.04354929924011, 40.689676800252016 ],
[ -74.04715418815613, 40.690994683044906 ]
]
]
}
}
]
}
I can serialize it using json.dumps:
print(json.dumps(fc))
This prints out the JSON:
{"type": "FeatureCollection", "features": [{"type": "Feature", "properties": {"name": "Liberty Island", "area_sqm": 24950.40123456, "established": 1875, "height_ft": 305}, "geometry": {"type": "Polygon", "coordinates": [[[-74.04715418815613, 40.690994683044906], [-74.04499769210815, 40.68873311507798], [-74.04354929924011, 40.689676800252016], [-74.04715418815613, 40.690994683044906]]]}}]}
Those coordinates are far too precise. According to Wikipedia, 7 digits is ~cm precision, which ought to be good enough. What I'm getting is ~nanometer precision.
I'd like to serialize the GeoJSON FeatureCollection with only seven digits of precision for coordinates. Note that I'd like to use Python's default serialization for everything in properties: since the values there could be anything, I can't make any universal claims about how much precision is enough.
My desired output is something like:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"name": "Liberty Island",
"area_sqm": 24950.40123456,
"established": 1875,
"height_ft": 305
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[ -74.0471541, 40.6909946 ],
[ -74.0449976, 40.6887331 ],
[ -74.0435492, 40.6896768 ],
[ -74.0471541, 40.6909946 ]
]
]
}
}
]
}
I'm not sure what exact serialization you're after but when it comes to FeatureCollection simplification, this should get you started:
import json
from copy import copy
def simplify_geometries(feat_collection):
new_coll = copy(feat_collection)
old_features = new_coll['features']
new_features = []
for feature in old_features:
geometry = feature['geometry']
coords = shorten_arr(geometry['coordinates'])
geometry['coordinates'] = coords
new_features.append(feature)
new_coll['features'] = new_features
return json.dumps(new_coll)
print(simplify_geometries(
json.loads('{"type": "FeatureCollection",...')
))
where shorten_arr is a trivial recursion:
def shorten_arr(arr, dec_places=7):
if not isinstance(arr, list):
return round(arr, dec_places)
to_ret = []
for n in arr:
if isinstance(n, list):
n = shorten_arr(n, dec_places)
to_ret.append(shorten_arr(n, dec_places))
return to_ret
I have a Geojson as follows:
data = {
"type": "FeatureCollection",
"name": "entities",
"features": [
{
"type": "Feature",
"properties": {
"Layer": "0",
"SubClasses": "AcDbEntity:AcDbBlockReference",
"EntityHandle": "3C8",
"area": "141.81",
"type": "p",
"Text": "area:141.81;type:p"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
2721.1572741014097,
1454.3223948456648
],
[
2720.121847266826,
1454.3223948456648
],
[
2720.121847266826,
1452.6092152478227
],
[
2710.5679254269344,
1452.6092152478227
],
[
2721.1572741014097,
1430.1478385206133
],
[
2721.1572741014097,
1454.3223948456648
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Layer": "0",
"SubClasses": "AcDbEntity:AcDbBlockReference",
"EntityHandle": "3CE",
"area": "44.79",
"type": "h",
"Text": "area:44.79;type:h"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
2710.723323781393,
1450.3320226620049
],
[
2720.0654518264787,
1450.3320226620049
],
[
2720.0654518264787,
1445.537183875705
],
[
2710.723323781393,
1445.537183875705
],
[
2710.723323781393,
1450.3320226620049
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Layer": "0",
"SubClasses": "AcDbEntity:AcDbBlockReference",
"EntityHandle": "610",
"name": "706",
"area": "92.28",
"type": "o",
"Text": "name:706;area:92.28;type:o"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
2714.603212251531,
1462.7249212430308
],
[
2711.7289360797,
1462.7249212430308
],
[
2711.7289360797,
1464.852506681824
],
[
2705.7302059101926,
1460.6840827804538
],
[
2710.567925426934,
1454.3223948456637
],
[
2710.567925426934,
1453.838838298367
],
[
2714.603212251531,
1453.838838298367
],
[
2714.603212251531,
1462.7249212430308
]
]
]
}
}
]
}
I want to insert "name": "" if name does not exist in properties, and delete "Text" object since it's duplicated, how can I do that in Python?
Thanks a lot at advance!
Expected result:
data = {
"type": "FeatureCollection",
"name": "entities",
"features": [
{
"type": "Feature",
"properties": {
"Layer": "0",
"SubClasses": "AcDbEntity:AcDbBlockReference",
"EntityHandle": "3C8",
"name": "",
"area": "141.81",
"type": "p"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
2721.1572741014097,
1454.3223948456648
],
[
2720.121847266826,
1454.3223948456648
],
[
2720.121847266826,
1452.6092152478227
],
[
2710.5679254269344,
1452.6092152478227
],
[
2721.1572741014097,
1430.1478385206133
],
[
2721.1572741014097,
1454.3223948456648
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Layer": "0",
"SubClasses": "AcDbEntity:AcDbBlockReference",
"EntityHandle": "3CE",
"name": "",
"area": "44.79",
"type": "h"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
2710.723323781393,
1450.3320226620049
],
[
2720.0654518264787,
1450.3320226620049
],
[
2720.0654518264787,
1445.537183875705
],
[
2710.723323781393,
1445.537183875705
],
[
2710.723323781393,
1450.3320226620049
]
]
]
}
},
{
"type": "Feature",
"properties": {
"Layer": "0",
"SubClasses": "AcDbEntity:AcDbBlockReference",
"EntityHandle": "610",
"name": "706",
"area": "92.28",
"type": "o"
},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
2714.603212251531,
1462.7249212430308
],
[
2711.7289360797,
1462.7249212430308
],
[
2711.7289360797,
1464.852506681824
],
[
2705.7302059101926,
1460.6840827804538
],
[
2710.567925426934,
1454.3223948456637
],
[
2710.567925426934,
1453.838838298367
],
[
2714.603212251531,
1453.838838298367
],
[
2714.603212251531,
1462.7249212430308
]
]
]
}
}
]
}
UPDATE:
My solution so far, it seems works.
import json
features = data["features"]
for i in features:
d = i["properties"]
if "name" not in d:
d["name"] = ""
if i["properties"]["Text"] is not None:
del i["properties"]["Text"]
I define it as a function, but in some cases I get an error as follows. Does someone know how to fix it? Thanks.
Traceback (most recent call last):
File "<ipython-input-1-8e3095f67c57>", line 138, in <module>
modify_geojson(output_file)
File "<ipython-input-1-8e3095f67c57>", line 102, in modify_geojson
if i["properties"]["Text"] is not None:
KeyError: 'Text'
In each property 'Text' is only present once. Please explain where it's duplicated?
My solution so far, it seems works.
import json
features = data["features"]
for i in features:
d = i["properties"]
if "name" not in d:
d["name"] = ""
if i["properties"]["Text"] is not None:
del i["properties"]["Text"]
I define it as a function, but in some cases I get an error as follows. Does someone know how to fix it? Thanks.
Traceback (most recent call last):
File "<ipython-input-1-8e3095f67c57>", line 138, in <module>
modify_geojson(output_file)
File "<ipython-input-1-8e3095f67c57>", line 102, in modify_geojson
if i["properties"]["Text"] is not None:
KeyError: 'Text'