2014-09-20 76 views
1

我有類似下面的許多部分文件:如何將文件讀取爲多個多邊形的嵌套座標列表?

[40.742742,-73.993847] 
[40.739389,-73.985667] 
[40.74715499999999,-73.97992] 
[40.750573,-73.988415] 
[40.742742,-73.993847] 

[40.734706,-73.991915] 
[40.736917,-73.990263] 
[40.736104,-73.98846] 
[40.740315,-73.985263] 
[40.74364800000001,-73.993353] 
[40.73729099999999,-73.997988] 
[40.734706,-73.991915] 

[40.729226,-74.003463] 
[40.7214529,-74.006038] 
[40.717745,-74.000389] 
[40.722299,-73.996634] 
[40.725291,-73.994413] 
[40.729226,-74.003463] 
[40.754604,-74.007836] 
[40.751289,-74.000649] 
[40.7547179,-73.9983309] 
[40.75779,-74.0054339] 
[40.754604,-74.007836] 

我需要在每一部分作爲對座標列表的閱讀(每區一個額外的\n分隔)。

在一個類似的文件我有(除相同,沒有額外的換行符休息),我繪製一條從整個文件一個多邊形。我可以使用下面的代碼中的座標讀取和matplotlib繪製:

mVerts = [] 
with open('Manhattan_Coords.txt') as f: 
    for line in f: 
     pair = [float(s) for s in line.strip()[1:-1].split(", ")] 
     mVerts.append(pair) 

plt.plot(*zip(*mVerts)) 
plt.show() 

我怎麼能完成同樣的任務,除了有許多超過1個多邊形,在我的文件中的每個多邊形通過一個額外的換行分隔?

+0

爲什麼換行relavent?表單是'[#,#]'。你的意思是可能有'[#,#] [#,#] [#,#] \ n'這3個座標與其他座標分開嗎? – sln 2014-09-20 23:17:00

+0

[#,#] \ n [#,#] \ n。 。 。 \ n [#,#] \ n \ n是一個多邊形,在換行之前有任意給定的座標數 – jqwerty 2014-09-20 23:18:34

+0

那麼你可以將每行解析爲一個字符串,然後建立一個正則表達式來查找每一對。這是否是你有麻煩的正則表達式,比如去除裝飾'[,]'? – sln 2014-09-20 23:22:13

回答

4

這是我個人最喜歡的方式,以「塊」文件到由空格分隔的東西組:

from itertools import groupby 

def chunk_groups(it): 
    stripped_lines = (x.strip() for x in it) 
    for k, group in groupby(stripped_lines, bool): 
     if k: 
      yield list(group) 

而且我建議ast.literal_eval把名單的那些字符串表示爲實際的Python列表:

from ast import literal_eval 

with open(filename) as f: 
    result = [[literal_eval(li) for li in chunk] for chunk in chunk_groups(f)] 

給出:

result 
Out[66]: 
[[[40.742742, -73.993847], 
    [40.739389, -73.985667], 
    [40.74715499999999, -73.97992], 
    [40.750573, -73.988415], 
    [40.742742, -73.993847]], 
[[40.734706, -73.991915], 
    [40.736917, -73.990263], 
    [40.736104, -73.98846], 
    [40.740315, -73.985263], 
    [40.74364800000001, -73.993353], 
    [40.73729099999999, -73.997988], 
    [40.734706, -73.991915]], 
[[40.729226, -74.003463], 
    [40.7214529, -74.006038], 
    [40.717745, -74.000389], 
    [40.722299, -73.996634], 
    [40.725291, -73.994413], 
    [40.729226, -74.003463], 
    [40.754604, -74.007836], 
    [40.751289, -74.000649], 
    [40.7547179, -73.9983309], 
    [40.75779, -74.0054339], 
    [40.754604, -74.007836]]] 
2

略有差來對roippi的思想,採用json代替ast

import json 
from itertools import groupby 

with open(FILE, "r") as coodinates_file: 
    grouped = groupby(coodinates_file, lambda line: line.isspace()) 
    groups = (group for empty, group in grouped if not empty) 

    polygons = [[json.loads(line) for line in group] for group in groups] 
from pprint import pprint 
pprint(polygons) 
#>>> [[[40.742742, -73.993847], 
#>>> [40.739389, -73.985667], 
#>>> [40.74715499999999, -73.97992], 
#>>> [40.750573, -73.988415], 
#>>> [40.742742, -73.993847]], 
#>>> [[40.734706, -73.991915], 
#>>> [40.736917, -73.990263], 
#>>> [40.736104, -73.98846], 
#>>> [40.740315, -73.985263], 
#>>> [40.74364800000001, -73.993353], 
#>>> [40.73729099999999, -73.997988], 
#>>> [40.734706, -73.991915]], 
#>>> [[40.729226, -74.003463], 
#>>> [40.7214529, -74.006038], 
#>>> [40.717745, -74.000389], 
#>>> [40.722299, -73.996634], 
#>>> [40.725291, -73.994413], 
#>>> [40.729226, -74.003463], 
#>>> [40.754604, -74.007836], 
#>>> [40.751289, -74.000649], 
#>>> [40.7547179, -73.9983309], 
#>>> [40.75779, -74.0054339], 
#>>> [40.754604, -74.007836]]] 
2

有很多在已經發布的答案拍攝漂亮的方法。他們中的任何一個都沒有問題。

不過,也無可厚非採取明顯的,但可讀的方式。

在一個側面說明,你似乎對地理數據的工作。這種格式是所有時候都會遇到的,並且段定界符通常不像額外的換行符那樣明顯。 (有很多相當不錯的ad-hoc「ASCII導出」的格式在那裏,特別是在不起眼的專有軟件。例如,一個常見的格式使用的F在最後一行在段分隔符結束時(即1.0 2.0F )許多其他人根本不使用分隔符,並且如果距離最後一點距離「x」以上,則需要開始一個新的分段/多邊形。)此外,這些東西通常會變成多個-GB ascii文件,因此將整個內容讀入內存可能不切實際。


我的觀點是:無論您選擇何種方法,請確保您瞭解它。你將會再次這樣做,而且它會變得不同以致難以概括。你絕對需要好好學習itertools這樣的庫,但要確保你完全理解你所調用的函數。


下面是「明顯但可讀」方法的一個版本。它更加冗長,但沒有人會因爲它的作用而撓頭。 (你可以用幾種不同的方式編寫相同的邏輯。使用什麼最有意義給您。)

import matplotlib.pyplot as plt 

def polygons(infile): 
    group = [] 
    for line in infile: 
     line = line.strip() 
     if line: 
      coords = line[1:-1].split(',') 
      group.append(map(float, coords)) 
     else: 
      yield group 
      group = [] 
    else: 
     yield group 

fig, ax = plt.subplots() 
ax.ticklabel_format(useOffset=False) 

with open('data.txt', 'r') as infile: 
    for poly in polygons(infile): 
     ax.plot(*zip(*poly)) 

plt.show() 

enter image description here

+0

這看起來不錯,但是當我嘗試運行它時出現錯誤: Traceback(最近呼叫的最後一個): 文件「Tri_State_Maps.py」,第42行,在 ax.plot(* zip(* poly)) ValueError:無法將字符串轉換爲浮點型:' - ' – jqwerty 2014-09-21 02:24:47