Mehr

Verwenden von PyShp zum Konvertieren von Polygonen in *.csv- in *.shp-Dateien?


Ich konvertiere CSV-Daten mit der Python-Bibliothek pyshp in Shapefiles. Was ich tun möchte, ist der .csv-Datei in .shp? mit pyshp konvertieren sehr ähnlich, außer dass ich nicht weiß, wie man mit Polygonen umgeht.

Meine Daten sind in einer csv-Datei. Jede Zeile entspricht einem benannten Rechteck, d. h. einer Zeichenfolge und den Breiten- oder Längenkoordinaten jeder Seite des Rechtecks: linke Seite (xl), rechte Seite (xr), oben (yt) und unten (yb).

Meine Daten sehen also so aus:

name,xl,xr,yt,yb irgendein Name,-25.3125,22.5,47.517193,31.353634 ein anderer Name,-103.359375,-0.703125,80.872,74.40216…

Und mein Python-Code ist ziemlich einfach. Es ist nur geringfügig vom Punktebeispiel abgewandelt. Aber wenn ich versuche, diese Daten in Google Maps zu importieren, treten beim Parsen einige Fehler auf. Ich glaube, ich mache etwas falsch, bin mir aber nicht sicher, was?

#Erstellen Sie leere Listen für den Datennamen, polyPart = [],[] #lesen Sie Daten aus der CSV-Datei und speichern Sie sie in Listen mit open(in_file, 'rb') als CSV-Datei: r = csv.reader(csvfile, delimiter=", ") for i,row in enumerate(r): if i > 0: #skip header # parse Daten in ein Punktarray, das die Bounding Box darstellt xl = float(row[1]) xr = float(row[2]) yt = float(row[3]) yb = float(row[4]) tl = [xl, yt] tr = [xr, yt] br = [xr, yb] bl = [xl, yb] parr = [tl, tr, br, bl, tl] # Array eines "Teils", das Teil ist ein Array von Punkten polyPart.append([parr]) name.append(row[0]) #Shapefile-Writer einrichten und leere Felder erstellen maxStringLength = 50 w = shp.Writer(shp.POLYGON) w.field('name','C',maxStringLength) #Schleife durch die Daten und schreibe das Shapefile für j, name in enumerate(name): w.poly(parts =polyPart[j]) w.record(name) #Shapefile speichern w.save(out_file)

Ihr Ansatz ist gut, aber Sie könnten die Dinge mit Wörterbüchern anstelle von Listen klarer machen und das CSV-Modul ermöglicht dies.
Darüber hinaus verwendet Ihr Skript zwei Schleifen, während es möglich ist, nur eine zu verwenden (die zweite Schleife ist redundant, eine Zeile der CSV-Datei = ein Datensatz des Shapefiles).

1) Mit Wörterbüchern:

Auslesen der csv-Datei:

with open('your.csv', 'rb') as f: reader = csv.DictReader(f) für Zeile in reader: print row {'xr': '22.5', 'yb': '31.353634', 'name ': 'irgendeiner Name', 'xl': '-25.3125', 'yt': '47.517193'} {'xr': '-0.703125', 'yb': '74.40216', 'name': 'anderer Name' , 'xl': '-103.359375', 'yt': '80.87282'}

Sie können jetzt row['xr'] oder row['name'] anstelle von row[n] verwenden (expliziter)

So wird Ihr Skript:

import csv polyName, polyPart = [],[] with open('your.csv', 'rb') as f: reader = csv.DictReader(f) for row in reader: bl = [float(row['xl' ]),float(row['yb'])] tl = [float(row['xl']),float(row['yt'])] br = [float(row['xr']),float (row['yb'])] tr = [float(row['xr']),float(row['yt'])] parr = [tl, tr, br, bl, tl] polyName.append(row ['Name']) polyPart.append(parr)

Schreiben des Polygon-Shapefiles

Wenn Sie sich PyShpDocs ansehen, können Sie Folgendes sehen:

Ein Polygon wird definiert durch:

w = shapefile.Writer(shapefile.POLYGON) w.line(parts=[[[1,5],[5,5],[5,1],[3,3],[1,1]]])

und das Skript ist, wie du geschrieben hast:

import shapefile # erstelle das Polygon Shapefile w = shapefile.Writer(shapefile.POLYGON) # das Feld w.field('name','C',maxStringLength) # schreibe die Polygone in das Shapefile für part,name in zip(polyPart, polyName): w.poly(parts=[part]) w.record(name) #save the shapefile w.save('your.shp')

2) Endgültige Lösung mit nur einer Schleife

Aber die zweite Schleife ist hier nicht notwendig: Sie können alles mit einer Schleife erledigen (Lesen der CSV-Datei und Schreiben des Shapefiles ohne Verwendung der polyName- und polyPart-Listen).

w = shapefile.Writer(shapefile.POLYGON) w.field('name','C',50) with open('your.csv', 'rb') as f: reader = csv.DictReader(f) for row im Reader: bl = [float(row['xl']),float(row['yb'])] tl = [float(row['xl']),float(row['yt'])] br = [float(row['xr']),float(row['yb'])] tr = [float(row['xr']),float(row['yt'])] parr = [tl, tr, br, bl, tl] w.poly(parts=[parr]) w.record(row['name']) w.save("your.shp')

Ergebnis in QGIS:


Es ist keine gute Programmierpraxis, Ihre Iteratorvariable in einer for-Schleife auf denselben Namen der Liste zu setzen, die Sie durchlaufen. Sie sollten einen der . ändernNameVariablen.

Ich habe Ihren Code auf meinem Computer mit Ihrem kleinen Datensatz ausgeführt und das Shapefile korrekt erstellt. Ich kann es zusammen mit der Attributtabelle in ArcMap anzeigen. Natürlich ist diesen Daten kein Raumbezug zugeordnet, daher sollten Sie wahrscheinlich einen wie hier beschrieben definieren. Ich würde dies auf jeden Fall implementieren, bevor ich weitermache.

Auf jeden Fall wird es Ihnen leichter fallen, damit zu arbeiten. Ich habe (hoffentlich) ein paar Dinge vereinfacht:

import shapefile as shp import csv in_file = "C:/users/paul/desktop/test.csv" out_file = "C:/users/paul/desktop/test.shp" #Erstelle leere Listen für Daten polyName, polyPart = [ ],[] #Daten aus csv-Datei lesen und in Listen mit open(in_file, 'rb') als csv-Datei speichern: r = csv.reader(csvfile, delimiter=",") #Header automatisch überspringen. next(r, None) für Zeile in r: # Daten in ein Punktarray parsen, das den Begrenzungsrahmen darstellt xl = float(row[1]) xr = float(row[2]) yt = float(row[3]) yb = float(row[4]) tl = [xl, yt] tr = [xr, yt] br = [xr, yb] bl = [xl, yb] parr = [tl, tr, br, bl, tl] # Array aus einem "Teil", das Teil ist ein Array von Punkten polyPart.append([parr]) polyName.append(row[0]) #Shapefile-Writer einrichten und leere Felder erstellen maxStringLength = 50 w = shp.Writer(shp .POLYGON) w.field('name','C',maxStringLength) #Schleife durch die Daten und schreibe das Shapefile für part,name in zip(polyPart, polyName): w.poly(parts=part) w.record( name) #Shapefile speichern w.save(out_file)

Sie könnten dies in wenigen Zeilen mit Shapely und GeoPandas tun (das Fiona unter der Haube für die Datei-I / O verwendet). Sie können verwendenformschöne.geometrie.boxUm die Rechtecke zu erstellen, wandeln Sie es in a . umGeoDataFrame, und verwenden Sie dieeinordnenMethode zum Speichern als Shapefile:

from pandas import DataFrame from geopandas import GeoDataFrame from shapely.geometry import box data = DataFrame.from_csv('rect.csv') boxen = [box(row['xl'], row['yb'], row['xr' ], row['yt']) für Schlüssel, Zeile in data.iterrows()] df = GeoDataFrame(boxes, column=['geometry'], index=data.index) df.to_file('out.shp', driver="ESRI Shapefile")

Hier ist der Code, der mit Shapefile geschrieben wurde, jede Zeile gut kommentiert importieren, um den Code effizient zu schreiben. es schreibt das Shapefile mit Projektion.

Shapefile importieren CSV importieren Import ast # csv mit open(r"Sample_Data.csv", encoding="utf8") als csvfile lesen: # dict create dictReader=csv.DictReader(csvfile) # beschreibbares Shapefile erstellen w = shapefile.Writer(' Sample_Data.shp') # Attribut erstellen w.field('id', 'C') w.field('nieghborho', 'C') w.field('plan_no', 'C') # Zeile aus dict für Zeile in dictReader: # schreibe Zeilenattribut w.record(row['id'], row['nieghborhood'], row['plan_no']) # schreibe geom w.poly([ast.literal_eval(row['geom'] )]) # prj-Datei erstellen prj = open("Sample_Data.prj", "w") epsg = 'GEOGCS["WGS 84",' epsg += 'DATUM["WGS_1984",' epsg += 'SPHEROID[" WGS 84",6378137,298.257223563]]' epsg += ',PRIMEM["Greenwich",0],' epsg += 'UNIT["degree",0.0174532925199433]]' # prj-Datei speichern prj.write(epsg) # über Shapefile schließen w.close()


Schau das Video: EXCEL Vers Shapefile CSV to SHP QGis (Oktober 2021).