Python Script in ArcGIS (List loop)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
PythonArcGIS
User
Beiträge: 5
Registriert: Dienstag 20. November 2012, 19:25

Hoffentlich könnt ihr mir helfen, ich möchte mir auf der Arbeit das Leben etwas erleichtern

Ich möchte mehrere Buffer auf eine Objektklasse berechnen und dafür eine Batch schreiben:

Code: Alles auswählen

import arcpy

arcpy.env.overwriteOutput = 1

arcpy.env.workspace = "d:\\xxx.mdb"

Eingabe = raw_input("Namen für die Dateien angeben: ")

out = [Eingabe+"1", Eingabe+"2", Eingabe+"3", Eingabe+"4"]
for output in out:
      arcpy.Buffer_analysis ("strassen", output, 200)
print "fertig"
Soweit so gut, es wird ein Buffer mit 200 Metern erzeugt und in 4 verschiedenen Objektklassen abgespeichert. Es funktioniert auch und jetzt kommt die Herausforderung!!! Es soll natürlich auch eine Schleife für die Buffergröße gebaut werden, um in den 4 Objektklassen verschiedene Buffer zu haben und damit habe ich Probleme. Wie verschachtele ich also die beiden Schleifen???

z.B.

Code: Alles auswählen

out = [userEingabe+"100", userEingabe+"150", userEingabe+"200", userEingabe+"250"]
for output in out:
        buffer = [100, 150, 200, 250]
	        for buffer_output in buffer:
		        arcpy.Buffer_analysis ("strassen", output, buffer_output)
print "fertig"
oder

Code: Alles auswählen

out = [userEingabe+"100", userEingabe+"150", userEingabe+"200", userEingabe+"250"]
buffer = [100, 150, 200, 250]
for output in out:
      for buffer_output in buffer:
            arcpy.Buffer_analysis ("strassen", output, buffer_output)
print "fertig"
Beide Variaten funktionieren nicht ... aber ich denke ihr wisst nun was ich meine.

Gruß
Martin
Zuletzt geändert von PythonArcGIS am Donnerstag 22. November 2012, 11:30, insgesamt 1-mal geändert.
PythonArcGIS
User
Beiträge: 5
Registriert: Dienstag 20. November 2012, 19:25

Kann mir niemand helfen?
BlackJack

@PythonArcGIS: Ich habe das Gefühl man muss ArcGIS kennen um zu verstehen was Du erreichen möchtest.

Und selbst dann ist ein „eide Varianten funktionieren nicht” vielleicht keine ausreichende Beschreibung von dem was da passiert. Denn irgendetwas wird ja passieren, allerdings etwas was nicht Deinen Erwartungen entspricht.

Wobei man beim ersten Beispiel schon vom anschauen des Quelltextes sagen kann, dass das einen `IndentationError` geben wird.

Das zweite Argument von `Buffer_analysis()` scheint eine Ausgabedateiname zu sein — kann man denn überhaupt dort einen bereits vorhandenen Dateinamen angeben? Wird diese Datei dann erweitert oder einfach nur überschrieben?

Die Namensgebung ist auch etwas verwirrend. `out` und `buffer` klingen nicht nach Container-Objekten. `out_filenames` und `buffer_values` sagen besser aus um was es sich handelt.

In welchem Zusammenhang stehen die Werte dieser beiden Listen eigentlich? Irgendwie scheint es mir nämlich auch ein wenig sinnfrei viermal das selbe unter unterschiedlichen Namen zu berechnen‽ Soll die `Buffer_analysis()`-Funktion in dem Beispiel tatsächlich 12 mal ausgeführt werden? Schreib doch mal eine ``print``-Anweisung vor diesen Aufruf, welche die Argumente für den Aufruf ausgibt.

Oder willst Du am Ende gar nur vier Analysen durchführen, für die Bufferwerte bei denen der Bufferwert jeweils an den Ausgabenamen angehängt wird?
PythonArcGIS
User
Beiträge: 5
Registriert: Dienstag 20. November 2012, 19:25

Für die Verwendung des Moduls arcpy sollte man wirklich ArcGIS kennen, aber ich denke mir das eine List Loop Verschachtelung auch bei anderen Anwendungen vorkommt.

Der erste Quelltext funktioniert ohne Error, habe ich gerade nochmal getestet.

Der Ausgabedateiname ist der, den man als Benutzer unter "raw_input" eingibt. Ein vorhandener Dateiname wird nicht eingegeben. Die Dateien werden mit "arcpy.Buffer_analysis()" erzeugt.

Ja, die Variablen sind ein wenig verwirrend, ich habe sie nur schnell als Bsp. vergeben, aber das ist ja nicht das Problem. Man kann jederzeit Andere vergeben.

Natürlich macht es keinen Sinn 4 Dateien mit dem geleichen Buffer zu berechen, deswegen sollen auch 2 List Loops in "arcpy.Buffer_analysis()" enthalten sein. Die eine Schleife für die eingegebenen Buffergrößen und die andere Schleife für die Dateinamen. Alles soll in einem Durchgang / Funktion erstellt bzw. berechnet werden.

Also z.B. Datei1 zu Buffer100 und Datei2 zu Buffer200 usw.

Die Funktion soll nicht 12mal ausgeführt werden, nur 4 mal. Der Quelltext 2 und 3 ist als Ersatz in dem Quelltext 1 an der gleichen Stelle gedacht. Also statt nur einer Schleife im Quelltext 1 sollen nun 2 Schleifen in einer Funktion ausgeführt werden.

In den Quelltexten 2 und 3 bekomme ich die Meldung, dass die Datei userEingabe100 (bei mir "test100") schon vergeben ist und nicht überschrieben werden kann (verstehe ich auch nicht, da overwrite = 1 ist) bzw. werden alle 4 Dateien erstellt aber leider auch mit der gleichen Buffergröße.

Ja, die Buffergröße soll dem Anhang der Datei entsprechen, dass funktioniert auch.

Also wie führe ich 2 Schleifen in einer Funktion aus, um verschiedene Dateinamen zu erhalten und darin auch noch andere Werte berechnet werden?

Vielen Dank

Martin
BlackJack

@PythonArcGIS: Ich meinte das erste Beispiel mit zwei Schleifen, da ist ein Einrückungsfehler.

Es werden vorhandene Dateien überschrieben weil Du die innere Schleife drei mal für jeden Ausgabenamen ausführst.

Auch wenn man jederzeit andere Namen vergeben kann, sollte man das gleich zu Anfang richtig machen. Insbesondere wenn man den Quelltext anderen Leuten zeigt, dass die dann nicht wegen der Namen verwirrt sind und sich unnötig mit rätseln aufhalten müssen.

Bei Deinen verschachtelten Schleifen *wird* `Buffer_analysis()` 12 mal aufgerufen. Für jeden Dateinamen werden nacheinander alle Buffer-Grössen berechnet, wobei die Ergebnisse immer überschrieben werden, so dass am Ende immer die letzte Grösse in jeder Datei steht. Du solltest echt mal ein ``print`` vor die Berechnung einfügen um zu sehen wie oft und mit welchen Werten die Funktion ausgeführt wird. Der Block der äusseren Schleife wird für jeden Namen einmal ausgeführt. Also wird in dem Beispiel die innere Schleife vier mal ausgeführt. Die innere Schleife wird für jede Buffer-Grösse einmal ausgeführt, also insgesamt drei mal. Das führt dazu, dass die Analyse-Funktion insgesamt 4·3=12 mal aufgerufen wird.

So langsam habe ich aber den Eindruck bei Deinem Beispiel sind nicht nur die Namen schlecht gewählt, sondern auch die Beispieldaten. Ist das gewollt, dass die Zahlen bei den Ausgabenamen andere sind als bei den Buffer-Grössen und das es vier Namen aber nur drei Buffer-Grössen gibt? Denn dann habe ich immer noch nicht verstanden was Du überhaupt als Ergebnis haben möchtest.

Kann es sein dass Du n Buffer-Grössen hast und daraus n Dateien erzeugen möchtest wo die jeweilige Buffer-Grösse im Namen steht? Also zum Beispiel die Grössen [100, 200, 350] und der Benutzer gibt 'test' ein, und daraus sollen Dateien mit den Namen 'test100', 'test200', und 'test350' mit den entsprechenden Buffer-Grössen werden? Dann hättest Du Dein Problem wirklich extrem unpräzise und schlampig beschrieben und dann brauchst Du auch nur eine Schleife. Dann solltest Du mal ein Tutorial durcharbeiten was die Grundlagen und Kontrollstrukturen erklärt.
PythonArcGIS
User
Beiträge: 5
Registriert: Dienstag 20. November 2012, 19:25

Oh ja, da war ein Fehler. Entschuldigung wegen der Verwirrung. Es waren mehrer Versuche und ich habe den teilweise den falschen Quelltext kopiert.

Ich hatte mal einen Grundkurs in Python, ist aber schon länger her und versuche mich nun mit der ArcGIS Hilfe selbst in das Thema einzuarbeiten.

Ja, ich weiß das es 12mal in diesem Loop ausgegeben wird. Über eine print Funktion würde es so ausehen:

test 100 100
test 100 150
test 100 200
test 100 250
test 200 100
test 200 150
usw.
... also ingesamt 12.

Ich weiß aber nicht wie ich es sonst realisieren soll. Ich brauche doch 2 Schleifen, eine für die Dateien und Eine für die Buffergrößen.

Jetzt sind wir bei dem Problem angekommen, bei dem ich Deine / Eure Hilfe brauche.

Wie kann ich den richtigen Buffer in einer Schleife z.B. 100 und 150 usw. den entsprechenden Dateien zuweisen z.B. test100 und test 150?

Vielen Dank
BlackJack

@PythonArcGIS: Du hast glaube ich ganz grundsätzlich Schleifen noch nicht verstanden. Warum denkst Du dass Du zwei davon brauchst? Du hast, sagen wir mal vier Buffer-Grössen und dazu vier Ausgabenamen. Also musst Du die Analyse viermal wiederholen. In *einer* Schleife.

Dazu müsstest Du wenn Grössen und Namen in zwei Listen stehen über diese beiden Listen gleichzeit iterieren, quasi im Gleichschritt. Dafür gibt es die Funktion `zip()` die eine neue Liste mit zusammengehörigen Paaren von Elementen erstellt, oder `itertools.izip()` die im Grunde das gleiche macht, nur ohne die Liste tatsächlich zu erstellen. Das sollte man spätestens bei grösseren Datenmengen vermeiden.

Generell sollte man aber auch vermeiden zusammengehörende Daten in verschiedenen, „parallelen” Datenstrukturen zu halten. Dann passieren nämlich leicht solche Dinge wie in Deinem Beispiel, wo es verwirrend ist, dass die beiden Listen nicht gleich lang sind, und man raten musste was gemeint war.

In diesem speziellen Fall braucht man aber sowieso nur *eine* Liste und zwar die mit dem Grössen. Der Name kann ja innerhalb der Schleife aus der Eingabe vom Benutzer und der aktuellen Grösse vom Programm gebildet werden. Da ist das zweite Problem mit Deinem Beispiel: Die Werte in der Namen und der Grössenliste haben nicht zusammen gepasst. Aus dem Grund sollte man es vermeiden die gleiche Information von Hand mehrfach in den Quelltext zu schreiben. Wenn sich ein Wert aus anderen bereits gegebenen Werten berechnen lässt, sollte man das den Rechner erledigen lassen. Der macht das zuverlässiger. Beim erstellen kann man keinen Tippfehler machen (oder es ist wenigstens konsequent falsch), und wenn man das Programm mal abändert, muss man das nur an einer Stelle tun und nicht schauen wo man noch etwas ändern muss, wenn es noch andere literale Werte gibt, die vom geänderten Wert abhängen.

Für Deine Schleife bedeutet das letztendlich:

Code: Alles auswählen

for buffer_size in [100, 150, 200, 250]:
    arcpy.Buffer_analysis('strassen', base_name + str(buffer_size), buffer_size)
PythonArcGIS
User
Beiträge: 5
Registriert: Dienstag 20. November 2012, 19:25

KLAR ... absolut einleuchtend :oops:

Auf die Idee kam ich einfach nicht ... ich habe schon versucht die ganze Sache mit der "Exists" Funktion abzufangen, aber dann hätte ich auch jeden Buffer einzelnd berechnen können.

Vielen vielen lieben Dank, jetzt kann ich endlich den Sicherheitsabstand zu den Straßen einhalten bzw. die Entfernung prüfen.
CosmicBandit
User
Beiträge: 1
Registriert: Sonntag 20. April 2014, 16:32

Da ich eine ähnliche Fragestellung habe, dachte ich mir ich klinke mich hier mal mit ein!
Ich habe die Aufgabenstellung mit einem List Schleife gelöst, soweit so gut

Code: Alles auswählen

import arcpy
arcpy.env.overwriteOutput = 1
arcpy.env.workspace="C:\\salzburg.gdb"
sbgFluesse="sbg_fluesse"
buff_name=raw_input("Bitte geben sie einen Dateinamen ein:")
for buffer_size in [100,200,300,450]:
    outfile="C:\\salzburg.gdb\\buffer_output"
    arcpy.Buffer_analysis(sbgFluesse,buff_name+str(buffer_size),buffer_size)
print "Berechnung abgeschlossen"

Falls der Dateiname aber schon existiert, soll nun der Nutzer solange zu einer wiederholten Eingabe aufgefordert werden bis ein Datensatzname gefunden wurde, der noch nicht existiert!

Ich würde hier imho den while- loop verwenden, bin mir aber nicht sicher wie ich das im obigen Code integrieren soll?!

Code: Alles auswählen

while arcpy.Exists(buff_name)==True:
            buff_name=raw_input("Please enter a new data set name")
         else:
              for buffer_size in [100,200,300,450]:
              outfile:....
              arcPyBuffer_analysis(....)
Geht das in die richtige Richtung, oder Totalausfall?

lg
Antworten