如何将python dict转换为表格标准的geojson文件?

时间:2016-06-28 09:48:00

标签: python dictionary geojson

我想将excel文件转换为geojson文件。字典就像:

[
{"NoAdresse": 42537006584, "NoUsager": 42537000086, "LatEffective": 45.83675, "LongDebut": 4.91956, "LatDebut": 45.75529, "LongEffective": 4.84574, "IdVehicule": "246Veh", "LatArrivee": 45.83492, "NoDemande": 42537000003, "LongArrivee": 4.84762}, 
{"NoAdresse": 42537007718, "NoUsager": 42537002720, "LatEffective": 45.83955, "LongDebut": 4.84574, "LatDebut": 45.83675, "LongEffective": 4.83098, "IdVehicule": "246Veh", "LatArrivee": 45.83935, "NoDemande": 42537000004, "LongArrivee": 4.83084}, 
{"NoAdresse": 42537005803, "NoUsager": 42537002424, "LatEffective": 45.98730, "LongDebut": 4.83098, "LatDebut": 45.83955, "LongEffective": 4.72695, "IdVehicule": "246Veh", "LatArrivee": 45.98174, "NoDemande": 42537000006, "LongArrivee": 4.73942}, 
{"NoAdresse": 42537005803, "NoUsager": 42537003576, "LatEffective": 45.98730, "LongDebut": 4.83098, "LatDebut": 45.83955, "LongEffective": 4.72695, "IdVehicule": "246Veh", "LatArrivee": 45.98174, "NoDemande": 42537000005, "LongArrivee": 4.73942}, 
{"NoAdresse": 42537004215, "NoUsager": 42537003576, "LatEffective": 45.93778, "LongDebut": 4.72695, "LatDebut": 45.9873, "LongEffective": 4.62676, "IdVehicule": "246Veh", "LatArrivee": 45.93784, "NoDemande": 42537000005, "LongArrivee": 4.62625}, 
{"NoAdresse": 42537004215, "NoUsager": 42537002424, "LatEffective": 45.93778, "LongDebut": 4.72695, "LatDebut": 45.9873, "LongEffective": 4.62676, "IdVehicule": "246Veh", "LatArrivee": 45.93784, "NoDemande": 42537000006, "LongArrivee": 4.62625}, 
{"NoAdresse": 42537004215, "NoUsager": 42537002720, "LatEffective": 45.93778, "LongDebut": 4.72695, "LatDebut": 45.9873, "LongEffective": 4.62676, "IdVehicule": "246Veh", "LatArrivee": 45.93784, "NoDemande": 42537000004, "LongArrivee": 4.62625}, 
{"NoAdresse": 42537004215, "NoUsager": 42537000086, "LatEffective": 45.93778, "LongDebut": 4.72695, "LatDebut": 45.9873, "LongEffective": 4.62676, "IdVehicule": "246Veh", "LatArrivee": 45.93784, "NoDemande": 42537000003, "LongArrivee": 4.62625}, 
{"NoAdresse": 42537000007, "NoUsager": 42537002425, "LatEffective": 45.72941, "LongDebut": 4.77845, "LatDebut": 45.77335, "LongEffective": 4.88396, "IdVehicule": "164Veh", "LatArrivee": 45.72815, "NoDemande": 42537000070, "LongArrivee": 4.88241}, 
{"NoAdresse": 42537000007, "NoUsager": 42537002425, "LatEffective": 45.69349, "LongDebut": 4.88396, "LatDebut": 45.72941, "LongEffective": 4.94466, "IdVehicule": "164Veh", "LatArrivee": 45.69429, "NoDemande": 42537000070, "LongArrivee": 4.94216}]

我使用此代码来实现此目的:

import json

from xlrd import open_workbook

book = open_workbook('forum.xlsx')
sheet = book.sheet_by_index(0)

keys = [sheet.cell(0,col_index).value for col_index in xrange(sheet.ncols)]

dict_list = []
for row_index in xrange(1,sheet.nrows):
    d = {keys[col_index]: sheet.cell(row_index,col_index).value
        for col_index in xrange(sheet.ncols)}
    dict_list.append(d)

j = json.dumps(dict_list)

with open('data.json','w') as f:
    f.write(j)

然后我想以下面的形式将它变成geojson文件:

{ "type": "FeatureCollection",
"features": [{ 
    "type": "Feature",
    "geometry": {
        "type": "LineString",
        "coordinates": [[LatDebut, LongDebut],[LatEffective,LongEffective]]
    },
    "properties": {
        "NoAdresse": "XXX",
        "NoUsager": "XXX",
        "NoDemand":"XXX",
        "IdVehicule":"XXX"
    }
}, { 
...
}]
}

我不知道该怎么做以及是否有另一种方法可以直接从excel转换为geojson文件。此外,我想添加一个属性“Tour”,每次“IdVehicule”改变时它都会改变。我知道要问这么多,但我已经坚持了很长时间,任何帮助都会受到赞赏。

由于

2 个答案:

答案 0 :(得分:0)

这是包[geojson] [1]:https://github.com/frewsxcv/python-geojson

答案 1 :(得分:0)

因此,如果您知道如何将dict“按摩”到您想要的最终结构中 - 将所有“其他元素”移动到某个属性成员中 - 那么我认为它就像

一样简单
# work on dict_list to produce some dict_in_geojson_form
# ... then:
with open('data.json','w') as f:
    json.dump(dict_in_geojson_form, f)

如果序列化仍不清楚,您可能还需要查看Python dump dict to json fileHow do I write JSON data to a file in Python? ...

高级更新:根据修改后的请求,添加了一些简单的转换和巡回枚举。请看下面的示例代码(在不同的代码框中分开,不必滚动...:

#! /usr/bin/env python
"""Map a specific stream to seom GeoJSON target structure and stream the
output in chunks as elements are complete (any new vehicle id increments
the tour label which works like an enumeration in the properties of the
features GeoJSON representation)."""
from __future__ import print_function

import copy
import json
import sys

#限制文字和准备结构的一些声明

NO_ADDRESS = 'NoAdresse'
NO_USAGE = 'NoUsager'
ID_VEHICLE = 'IdVehicule'
NO_DEMAND = 'NoDemande'

TOUR_LABEL = 'Tour'

PROPERTY_KEYS = (NO_ADDRESS, NO_USAGE, ID_VEHICLE, NO_DEMAND)

LAT_DEBUT = 'LatDebut'
LONG_DEBUT = 'LongDebut'
LAT_EFFECTIVE = 'LatEffective'
LONG_EFFECTIVE = 'LongEffective'

COORD_KEYS_DEBUT = (LAT_DEBUT, LONG_DEBUT)
COORD_KEYS_EFFECTIVE = (LAT_EFFECTIVE, LONG_EFFECTIVE)

PROPERTIES_KEY = 'properties'
GEOMETRY_KEY = 'geometry'
COORDINATES_KEY = 'coordinates'
FEATURES_KEY = 'features'

GEOJSON_FRAME_PREFIX = """{
"type": "FeatureCollection",
"features": [
"""

FEATURE_TEMPLATE = {
    "type": "Feature",
    GEOMETRY_KEY: {
        "type": "LineString",
        "coordinates": []
    },
    "properties": {
        NO_ADDRESS: None,
        NO_USAGE: None,
        NO_DEMAND: None,
        ID_VEHICLE: None,
        TOUR_LABEL: None
    }}

GEOJSON_LIST_SEP = ',\n'
GEOJSON_FRAME_POSTFIX = ']\n}\n'

#一个简单的功能发射源模拟

def event_source():
    """Sample input line source generator. Might anything yielding
    python dictionaries matching "this questions" event specification."""

    event_seq = [
        {NO_ADDRESS: 42537006584, NO_USAGE: 42537000086,
         LAT_EFFECTIVE: 45.83675, LONG_DEBUT: 4.91956,
         LAT_DEBUT: 45.75529, LONG_EFFECTIVE: 4.84574,
         ID_VEHICLE: "246Veh", "LatArrivee": 45.83492,
         NO_DEMAND: 42537000003, "LongArrivee": 4.84762},
        {NO_ADDRESS: 42537007718, NO_USAGE: 42537002720,
         LAT_EFFECTIVE: 45.83955, LONG_DEBUT: 4.84574,
         LAT_DEBUT: 45.83675, LONG_EFFECTIVE: 4.83098,
         ID_VEHICLE: "246Veh", "LatArrivee": 45.83935,
         NO_DEMAND: 42537000004, "LongArrivee": 4.83084},
        # ...
        {NO_ADDRESS: 42537000007, NO_USAGE: 42537002425,
         LAT_EFFECTIVE: 45.69349, LONG_DEBUT: 4.88396,
         LAT_DEBUT: 45.72941, LONG_EFFECTIVE: 4.94466,
         ID_VEHICLE: "164Veh", "LatArrivee": 45.69429,
         NO_DEMAND: 42537000070, "LongArrivee": 4.94216}]

    for event in event_seq:
        yield event

#无上下文转换:

def feature_from(event):
    """Transform event to feature, applying the "business" rules."""
    feature = copy.deepcopy(FEATURE_TEMPLATE)
    for property_key in PROPERTY_KEYS:
        feature[PROPERTIES_KEY][property_key] = event[property_key]
    coords_debut = [event[k] for k in COORD_KEYS_DEBUT]
    coords_effective = [event[k] for k in COORD_KEYS_EFFECTIVE]
    feature[GEOMETRY_KEY][COORDINATES_KEY].append(coords_debut)
    feature[GEOMETRY_KEY][COORDINATES_KEY].append(coords_effective)
    return feature

#分离的特征发射器(这里过度杀伤,但......)

def feature_gen(events):
    """Generator creates features from events (might be a good place
    to hook into validty checks in real lif processing)."""
    for event in events:
        yield feature_from(event)

#用于共享游览的特征序列的上下文感知生成器

def tour_gen(features):
    """Generator emits the feature in chunks per complete tour as detected
    by a change in vehicle id."""
    id_vehicle_active = None
    tour_enumeration = None
    for feature in features:
        id_vehicle_received = feature[PROPERTIES_KEY][ID_VEHICLE]
        if id_vehicle_active is None:
            id_vehicle_active = id_vehicle_received
            tour_enumeration = 1
            tour = []
        if id_vehicle_active != id_vehicle_received:
            yield tour
            tour = []
            tour_enumeration += 1
            id_vehicle_active = id_vehicle_received
            feature[PROPERTIES_KEY][TOUR_LABEL] = tour_enumeration
            tour.append(feature)
        else:
            feature[PROPERTIES_KEY][TOUR_LABEL] = tour_enumeration
            tour.append(feature)
    if tour:
        yield tour

#Mock函数将输出引导到stdout或文件...

def geojson_out(text, stream=sys.stdout):
    """Expected JSON text is output here."""
    stream.write(text)

#驱动转换的样本处理逻辑

def main():
    """Poor man's streaming falls back on hardcoded GeoJSON "frame"
    string as pre and post fix to the feature stream. the latter
    elements are accumulated in chunks carrying common "tour"
    enumeration label.

    The frame structure in Python lingo is:
        geo_dict = {"type": "FeatureCollection", "features": []}

    The features will be injected in the list and in this implementation
    need some stateful separator injection hack, to yield valid JSON
    (which does not allow trailing comma after last array elememt).
    """

#...此处作为写入硬编码文件路径的示例

    with open('yumyum.geojson', 'wt') as f_out:
        geojson_out(GEOJSON_FRAME_PREFIX, stream=f_out)
        json_array_nanny_needed = False  # Semi-auto, means semi-manual =(
        for features in tour_gen(feature_gen(event_source())):
            for feature in features:
                if json_array_nanny_needed:
                    geojson_out(GEOJSON_LIST_SEP, stream=f_out)
                geojson_out(json.dumps(feature, sort_keys=True), stream=f_out)
                json_array_nanny_needed = True  # HACK A DID ACK

        geojson_out(GEOJSON_FRAME_POSTFIX, stream=f_out)

if __name__ == '__main__':
    main()

处理中的想法应该在文档字符串中......

还可以收集/聚合/过滤每个车辆ID的坐标,或者......它是Python的通用编程语言; - )

在我的机器上,yumyum.txt中的输出是:

$ cat yumyum.geojson 
{
"type": "FeatureCollection",
"features": [
{"geometry": {"coordinates": [[45.75529, 4.91956], [45.83675, 4.84574]], "type": "LineString"}, "properties": {"IdVehicule": "246Veh", "NoAdresse": 42537006584, "NoDemande": 42537000003, "NoUsager": 42537000086, "Tour": 1}, "type": "Feature"},
{"geometry": {"coordinates": [[45.83675, 4.84574], [45.83955, 4.83098]], "type": "LineString"}, "properties": {"IdVehicule": "246Veh", "NoAdresse": 42537007718, "NoDemande": 42537000004, "NoUsager": 42537002720, "Tour": 1}, "type": "Feature"},
{"geometry": {"coordinates": [[45.72941, 4.88396], [45.69349, 4.94466]], "type": "LineString"}, "properties": {"IdVehicule": "164Veh", "NoAdresse": 42537000007, "NoDemande": 42537000070, "NoUsager": 42537002425, "Tour": 2}, "type": "Feature"}]
}