Attributtabelle sortieren

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.
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

Hallo,

kann mir jemand sagen, wie ich mit Hilfe eines Python-Skriptes eine Attributtabelle nach einer bestimmten Spalte, wo die Zahlenwerte noch durcheinaner gewürfelt sind, aufsteigend sortieren kann?
Benutzeravatar
lutz.horn
User
Beiträge: 205
Registriert: Dienstag 8. November 2005, 12:57
Wohnort: Pforzheim

Kannst Du ein paar mehr Details posten?
https://www.xing.com/go/invite/18513630.6a91d4
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

Ich habe ein Punkte-Shapefile mit verschiedenen Spalten und möchte jetzt die gesamte Tabelle nach einer bestimmten Spalte aufsteigend sortieren, wie es z.B. in der Attributtabelle mit rechtem Mausklick auf den Spaltenkopf und dann 'Sort Ascending' möglich ist
BlackJack

@Michi_J: Attributtabelle? Mausklick? Reden wir jetzt von einer Datenstruktur? Einer grafischen Anwendung? Welche?

Ansonsten gibt es auf Python's Listentyp eine `sort()`-Methode und es gibt eine `sorted()`-Funktion um aus beliebigen iterierbaren Objekten eine sortierte Liste zu generieren.

Wenn die "natürliche" Ordnung der Elemente nicht die richtige ist, haben sowohl die Methode als auch die Funktion ein Argument mit dem Namen `key` bei dem man eine Funktion angeben kann, die aus einem Element einen Sortierschlüssel generieren muss. Bei einfachen Sachen sind ``lambda``-Funktionen nützlich. Und eventuell auch `functools.partial()` in Verbindung mit `itemgetter()` oder `attrgetter()` aus dem `operator`-Modul.
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

das mit der Attributtabelle war nur zum besseren Verständnis gedacht, damit klar wird, was ich machen will.
Ich bin ziemlich neu hier und noch recht hilflos - bitte um Verzeihung.

Ich kann ja schon mal meinen Code posten, was ich mir bisher überlegt habe und bin über jede Anregung sehr dankbar, wie gesagt, ich bin noch ziemlich grün hinter den Ohren...

Code: Alles auswählen

import arcgisscripting          # import der Library
gp=arcgisscripting.create(9.3)  # geoprocessor zum import von funktionen
gp.workspace="C:/Temp"          # workspace

# table = Polyline0Punkte.shp --> an dieser Stelle sollte die Table eingelesen werden
import operator

def sort_table(table, col=2)
    return sorted(table, key=operator.itemgetter(col))

# nach dem sortieren soll die sortierte Table in eine Liste gepackt werden - ich weiß noch nicht, wie das funktioniert

sooo... das sieht zwar noch seeehr nach Anfänger aus, der keine Ahnung hat, aber das bin ich auch. Bitte um Hilfe!!!
Danke!
BlackJack

@Michi_J: `sorted()` liefert schon eine Liste als Ergebnis, das Problem im letzten Kommentar im Quelltext löst sich also von alleine.

Ich würde die Funktion etwas allgemeiner formulieren, also ohne `table` im Namen und nicht mit einer so ziemlich willkürlich erscheinenden Spalte als Defaultargument.

Code: Alles auswählen

def sorted_by_index(iterable, index)
    return sorted(iterable, key=operator.itemgetter(index))
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

@ BlackJack

muss der Input-Datensatz dann auch schon eine Liste sein? oder wie kann ich meine Table einlesen? Also ich hab jetzt mal meine Tabelle sozusagen in eine Liste eingefügt. Diese soll nun eben sortiert werden

Hier mein Vorschlag - dieser läuft aber nicht, immer Syntax-Fehlermeldung

Code: Alles auswählen

import arcgisscripting          # import der Library
gp=arcgisscripting.create(9.3)  # geoprocessor zum import von funktionen
gp.workspace="C:/Temp"          # workspace

 
cur=gp.SearchCursor("Polyline0Punkte.shp", "", "", "FID, FID_DREIEC, ORIG_FID, POINT_X,POINT_Y,POINT_Z,Tri_Index")      # Durchsuchen der Datei nach den Spalten X, Y, Z


#get the first value
row = cur.next()

# Iterate through the rows in the cursor
#
liste = list()
while row:
    current_FID = (row.FID)
    FID_Dreieck = (row.FID_DREIEC)
    FID_Polyline = (row.ORIG_FID)
    current_coordinate = (row.POINT_X, row.POINT_Y, row.POINT_Z)
    liste.append(current_FID)
    liste.append(FID_Dreieck)
    liste.append(FID_Polyline)
    liste.append(current_coordinate)

    row = cur.next()
    
import operator

def sort_table(iterable, index)
    return sorted(iterable, key=operator.itemgetter(2))

print liste
    
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Michi_J hat geschrieben:Hier mein Vorschlag - dieser läuft aber nicht, immer Syntax-Fehlermeldung
Traceback bitte posten!

Du willst im uebrigen `key=operator.itemgetter(index)` nutzen. Und den Import schreibt man ueblicherweise in den Anfang des Moduls.
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

aber muss ich den Index dann nicht definieren? Ich will ja die Liste nach dem 2. Eintrag sortieren...
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Du musst den Index sowieso uebergeben, also kannst du ihn auch benutzen.
Wenn du einen Shortcut nutzen willst kannst du folgendes machen:

Code: Alles auswählen

import functools
def sort_with_index(iterable, index)
    return sorted(iterable, key=operator.itemgetter(index))

sort_table = functools.partial(sort_with_index, index=2)
Und der Traceback?
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

bitte nicht lachen ... was ist der Traceback?
Benutzeravatar
Klip
User
Beiträge: 98
Registriert: Donnerstag 10. August 2006, 20:39

Die komplette Fehlermeldung.
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

und wie erkennt das Script, welche liste es sortieren soll?
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

Fehlermeldung: invalid syntax
BlackJack

@Michi_J: Das `iterable` Argument muss nur iterierbar sein. Darum habe ich es ja so genannt. ;-) Es geht also alles was bei `iter()` einen Iterator über die zu sortierenden Objekte liefert oder nach dem ``in`` in einer ``for``-Schleife verwendet werden kann.

Dein Programm hat ein logisches Problem: Du steckst die einzelnen Datensätze nicht als *ein* Objekt in die `liste`. Schau Dir mal an was da rauskommt. Viele von den Elementen dürften auf einen Versuch eines Indexzugriffs nicht so reagieren wie Du das wohl erwartest.

Aus der ``while``-Schleife würde ich eine ``for``-Schleife machen. Dann muss man nicht an zwei verschiedenen Stellen die `next()`-Methode selber aufrufen:

Code: Alles auswählen

for row in iter(cur.next, None):
    # ...

Der Traceback ist der Stapelabzug der bei Fehlermeldungen ausgegeben wird. Das Wort steht da doch auch ganz am Anfang:

Code: Alles auswählen

>>> 1 / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
Der enthält eine Auflistung aller Beteiligten Funktionen in der Aufrufhierarchie, die zu dem Fehler geführt haben, in der Regel auch mit den Zeilen aus den beteiligten Quelltextdateien. Das hilft beim Fehlersuchen.

Das Skript erkennt nicht welche Liste sortiert werden soll. Das musst Du schon sagen indem Du die Funktion mit den passenden Argumenten aufrufst und das Ergebnis zum Beispiel an einen Namen bindest.
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

hier nochmals mein Code:

Code: Alles auswählen

import arcgisscripting          # import der Library
gp=arcgisscripting.create(9.3)  # geoprocessor zum import von funktionen
gp.workspace="C:/Temp"          # workspace

 
cur=gp.SearchCursor("Polyline0Punkte.shp", "", "", "FID, FID_DREIEC, ORIG_FID, POINT_X,POINT_Y,POINT_Z,Tri_Index")      # Durchsuchen der Datei nach den Spalten X, Y, Z


#get the first value
row = cur.next()

# Iterate through the rows in the cursor
#
liste = list()
while row:
    current_Eintrag = (row.FID, row.FID_DREIEC, row.ORIG_FID, row.POINT_X, row.POINT_Y, row.POINT_Z)
    liste.append(current_Eintrag)
    liste.append(' ')

    row = cur.next()
    
#import operator

#def sort_table(iterable, index)
    #index = 2
    #return sorted(iterable, key=operator.itemgetter(index))
import functools
def sort_with_index(iterable, index)
    return sorted(iterable, key=operator.itemgetter(index))

sort_table = functools.partial(sort_with_index, index=2)


BlackJack

Der Traceback sollte am Ende eher so aussehen:

Code: Alles auswählen

   File "<file>", line 28
     def sort_with_index(iterable, index)
                                         ^
 SyntaxError: invalid syntax
Da gibt es also auch eine Quelltextzeile. Und einen "Pfeil" (^), der auf die Stelle zeigt, an welcher der Compiler nicht mehr weiter weiss. Und nun schau doch nochmal in der Dokumentation, was genau an der Stelle bei einer Funktionsdefinition erwartet wird.

Beim nächsten Versuch wird Dir wahrscheinlich ein `NameError` begegnen. Und wenn der behoben ist, und Du die Funktion auch mal tatsächlich aufrufst ist ein ``IndexError: string index out of range`` der nächste wahrscheinliche Kandidat. Aber eins nach dem anderen…
Zuletzt geändert von BlackJack am Montag 9. August 2010, 10:55, insgesamt 1-mal geändert.
Grund: Eine Zeile zum Traceback hinzugefügt.
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

worin liegt jetzt noch der Fehler, dass das Skript nicht läuft?

Code: Alles auswählen

import arcgisscripting          # import der Library
import operator
import functools
gp=arcgisscripting.create(9.3)  # geoprocessor zum import von funktionen
gp.workspace="C:/Temp"          # workspace

 
cur=gp.SearchCursor("Polyline0Punkte.shp", "", "", "FID, FID_DREIEC, ORIG_FID, POINT_X,POINT_Y,POINT_Z,Tri_Index")      # Durchsuchen der Datei nach den Spalten X, Y, Z


#get the first value
row = cur.next()

# Iterate through the rows in the cursor
#
liste = list()
for row in iter(cur.next, none):

    def sort_table(iterable, Index)
        return sorted(iterable, key=operator.itemgetter(index))
    sorted_table = operator(sort_table, 2)
    
    current_Eintrag = (row.FID, row.FID_DREIEC, row.ORIG_FID, row.POINT_X, row.POINT_Y, row.POINT_Z)
    liste.append(current_Eintrag)
    
    liste.append(' ')

    row = cur.next()
    

#def sort_with_index(iterable, index)
    #return sorted(iterable, key=operator.itemgetter(index))

#sort_table = functools.partial(sort_with_index, index=2)


print liste
    
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Anstatt auf geratewohl Dinge zu aendern, solltest du mal die Fehlermeldung verstehen! BlackJack hat es dir doch erklaert!
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Michi_J
User
Beiträge: 110
Registriert: Samstag 7. August 2010, 08:35

Ich krieg gar keinen Traceback-Eintrag im Python shell, da vorher schon ein Fenster erscheint in welchem genau folgende Mitteilung steht: There's an error in your program: invalid syntax
Antworten