Seite 1 von 2
Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 16:54
von Nobuddy
Hallo zusammen,
bin noch am Anfang, Python 3 zu erlernen.
Ich habe eine Datei, die aus 3 Spalten besteht.
Spalte 1 ist die Hauptgruppennummer, die von 1 bis 20 geht.
Spalte 2 sind zu Spalte 1 dazugehörige Untergruppen.
Spalte 3 beninhaltet eine fortlaufende Nummer und ist abhängig zu Spalte 1 und Spalte 2.
Ich poste hier mal einen kleinen Ausschnitt aus der Datei, damit Ihr Euch das besser vorstellen könnt.
- 1 FAXGERÄTE-ZUBEHÖR 1
1 KOPIERER-ZUBEHÖR 2
1 LASERDRUCKER-ZUBEHÖR 3
10 BAUMSCHMUCK 1
10 BRIEF&PAKETWAAGEN 2
10 BRIEFKARTEN 3
10 BUCHBOX-VERSANDTASCHEN 4
10 DATENTRÄGER-VERSAND 5
10 DEKORATIONEN 6
10 EINKAUFSKÖRBE 7
10 EISBLUMEN-SPRAY 8
10 FLORISTIK 9
11 SCHEREN 1
11 TECHNISCHES-ZEICHENPAPIER 2
11 TINTE&TUSCHE-IM-GLAS 3
11 TUSCHEFÜLLER&ZUBEHÖR 4
11 ZEICHENPLATTEN&ZUBEHÖR 5
11 ZIRKEL&ZIRKELMINEN 6
12 AQUARELL-FARBKÄSTEN 1
12 AQUARELL-KREIDEN 2
12 AQUARELL-PINSELSTIFTE 3
12 AQUARELL-STIFTE 4
12 BLEISTIFTE 5
12 CD-/DVD-MARKER 6
2 BRIEFUMSCHLÄGE 1
2 DESIGN-FOLIEN 2
2 ELEFANTENHAUT 3
2 ENDLOS-ETIKETTEN 4
2 ETIKETTEN-ABLÖSER 5
2 ETIKETTEN-FÜR-DRUCKMASCHINEN 6
2 FARBLASERDRUCKER-PAPIERE 7
2 FOLIEN-ETIKETTEN 8
2 FOTO-PAPIERE 9
2 KASSEN-/ADDITIONSROLLEN 10
2 KOPIER-PAPIERE 11
Nun suche ich eine Möglichkeit, den letzten (größten) Wert aus Spalte 3 zu ermitteln.
Beispiel:
Spalte 1: Hauptgruppennummer = 2
Spalte3: Maxwert = 11
Wie kann ich das bewerkstelligen?
Grüße Nobuddy
Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 17:03
von /me
Nobuddy hat geschrieben:Beispiel:
Spalte 1: Hauptgruppennummer = 2
Spalte3: Maxwert = 11
Wie kann ich das bewerkstelligen?
Oh, eine Datenbank für Arme.

So etwas liest man gerne mit dem
CSV-Modul aus.
Ich kann jetzt nicht absehen, in welche Richtung die Frage möglicherweise noch zielt, da ich nicht weiß, wie weit "am Anfang" du mit Python 3 bist.
Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 17:09
von nomnom
Du kannst die Spalten deines Datensatzes einlesen, indem du das `csv`-Modul einsetzt:
Code: Alles auswählen
import csv
with open('datensatz.csv') as f:
table = tuple(csv.reader(f))
Und dann kannst du die Funktion `max` benutzen, um die Spalte zu finden mit der größten Zahl als 3. Element:
Mit dem Parameter `key` kann man eine Funktion übergeben, die den Wert zurückgibt, der bestimmt, welche die größte Spalte ist. In dem Fall soll als `key` der Wert vom 3. Element gelten. `lambda`s sind eine spezielle Art von Funktionen, die nach dem
„Lambda-Kalkül“ definiert werden.
Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 18:10
von Nobuddy
Hallo nomnom,
habe das mal so übernommen
Code: Alles auswählen
import csv
with open(uigruppen_path) as f:
table = tuple(csv.reader(f))
biggest = max(table, key=lambda x: int(x[2]))
print(biggest)
Was folgende Meldung ausgibt:
Traceback (most recent call last): File "b_test.py", line 33, in <module>
biggest = max(table, key=lambda x: int(x[2]))
File "b_test.py", line 33, in <lambda>
biggest = max(table, key=lambda x: int(x[2]))
IndexError: list out of range
Dann habe ich das noch versucht
Code: Alles auswählen
with open(uigruppen_path, 'r') as f:
table = tuple(csv.reader(f, delimiter="\t"))
for line in table:
biggest = max(line, key=lambda x: int(x[2]))
print(biggest)
Was folgende Meldung ausgibt:
Traceback (most recent call last): File "b_test.py", line 33, in <module>
biggest = max(table, key=lambda x: int(x[2]))
File "b_test.py", line 33, in <lambda>
biggest = max(table, key=lambda x: int(x[2]))
ValueError: invalid literal for int() with base 10: '-'
Was läuft falsch, habe ich Dich falsch verstanden?
Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 18:29
von nomnom
Hoppsala, ich habe beim Schreiben vergessen, dass du ja Leerzeichen verwendest für deine Daten. (Denke ich.) Also müsstest du eigentlich als `delimiter` ein Leerzeichen einstellen. `csv.reader(f, delimiter=' ')`.
Edit: Kann es sein, dass dein Datensatz Artikel beinhaltet, die Leerzeichen/Tabs im Titel haben? Werden die Titel nicht mit „Quotes“ (Apostrophen?) eingeschlossen? Das ging aus deinem Beispiel ja nicht hervor. Mein Code + `delimiter`-Parameter funktioniert bei deinem Beispiel sowohl mit Tabs als auch mit Leerzeichen.
Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 18:40
von Nobuddy
nomnom hat geschrieben:Hoppsala, ich habe beim Schreiben vergessen, dass du ja Leerzeichen verwendest für deine Daten. (Denke ich.) Also müsstest du eigentlich als `delimiter` ein Leerzeichen einstellen. `csv.reader(f, delimiter=' ')`.
Nein, verwende Tabulator (\t) und Leerzeichen gibt es keine.
Habe es jetzt mal zum Laufen gebracht, ohne Fehlermeldung.
Code: Alles auswählen
with open(uigruppen_path, 'r') as f:
table = tuple(csv.reader(f, delimiter="\t"))
for line in table:
if line[0] != '---':
biggest = max(line, key=lambda x: int(line[2]))
print(biggest)
Leider kommt nich das Ergebnis, was ich mir vorgestellt habe.
Nochmal zurück zu meinem Beisspiel:
18 AKKU-ZAHNBÜRSTEN 1
18 ALLZWECKREINIGER 2
...
..
.
18 TOILETTENPAPIERE&ZUBEHÖR 29
18 WASCHMITTEL 30
18 WC-REINIGER 31
Wie Du hier siehst, hat Spalte 1 hier die Nummer 18.
Die Dritte Spalte zählt wird von der ersten 18 bis zur letzen Zeile numerisch durchgezählt.
Hier sollte dann die erste Spalte mit der dritten Spalte ausgegeben werden.
18 31
So würde ich mir das vorstellen.
Habe dies nur nochmals verdeutlicht, um kein Mißverständnis aufzukommen lassen.
Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 18:58
von Nobuddy
Habe zum obigen Beispiel, das Konstrukt mal angepasst.
Code: Alles auswählen
with open(uigruppen_path, 'r') as f:
table = tuple(csv.reader(f, delimiter="\t"))
x = 18
for line in table:
if line[0] == str(x) and line[2] != '---':
biggest = max(line, key=lambda x: int(line[2]))
print(biggest)
Was ich dabei aber als Ausgabe erhalte, ist nur die Spalte 1, also hier in diesem Fall die 18 statt der 31.
Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 19:08
von nomnom
Von den drei Minussen hast du uns nichts erzählt. Kannst du uns nochmal ein Beispiel aller möglichen Arten von Zeilen geben? Und so, wie du das versuchst, wird das leider garantiert nichts. Denn es macht keinen Sinn, in jeder Zeile nach dem größten Wert zu suchen, indem du immer den Wert der dritten Spalte vergleichst.
Edit: Mit
genau diesem Code und diesen Daten funktioniert es. Nur damit du siehst, dass es so eigentlich funktionieren sollte.

Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 19:28
von Nobuddy
nomnom hat geschrieben:Von den drei Minussen hast du uns nichts erzählt. Kannst du uns nochmal ein Beispiel aller möglichen Arten von Zeilen geben? Und so, wie du das versuchst, wird das leider garantiert nichts. Denn es macht keinen Sinn, in jeder Zeile nach dem größten Wert zu suchen, indem du immer den Wert der dritten Spalte vergleichst.
Ja, da bin ich auch drauf gekommen ... Schnapsidee.
Hier mal ein kleiner Auschnitt aus der Datei.
--- ZUBEHÖR-FÜR-ANSCHLUSSDOSEN ---
--- ZUBEHÖR-USV-ANLAGEN ---
1 ÖLFARBEN ---
1 FAXGERÄTE-ZUBEHÖR 1
1 KOPIERER-ZUBEHÖR 2
1 LASERDRUCKER-ZUBEHÖR 3
10 BAUMSCHMUCK 1
10 BRIEF&PAKETWAAGEN 2
10 BRIEFKARTEN 3
10 BUCHBOX-VERSANDTASCHEN 4
10 DATENTRÄGER-VERSAND ---
Habe das mit den '---' eingeschränkt.
Code: Alles auswählen
table_list = []
with open(uigruppen_path, 'r') as f:
reader = csv.reader(f, delimiter="\t")
for line in reader:
if line[0] != '---' and line[2] != '---':
table_list.append(line)
table = tuple(table_list)
biggest = max(table, key=lambda x: int(x[2]))
print(biggest)
Jetzt erhalte ich zwar ein richtiges Ergebnis, das aber den max-Wert der dritten Spalte ausgibt, ohne Berücksichtigung von Spalte 1. Also z.B.
Spalte 1 Nummer 1 maxwert 3
Spalte 1 Nummer 2 maxwert 25
Spalte 1 Nummer 3 maxwert 37
... usw.
Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 19:45
von nomnom
Wie meinst du das? Als Ergebnis kommt bei mir `['2', 'KOPIER-PAPIERE', '11']`. Ist das nicht, was du möchtest? Die Zeile mit der größten dritten Spalte inklusive Hauptgruppennummer.
Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 19:50
von Nobuddy
nomnom hat geschrieben:Wie meinst du das? Als Ergebnis kommt bei mir `['2', 'KOPIER-PAPIERE', '11']`. Ist das nicht, was du möchtest? Die Zeile mit der größten dritten Spalte inklusive Hauptgruppennummer.
JEIN, als Gruppierung soll Spalte 1 dienen.
Also von Hauptgruppennummer 1 den Maxwert x,
von Hauptgruppennummer 2 den Maxwert x,
von Hauptgruppennummer 3 den Maxwert x,
von Hauptgruppennummer 4 den Maxwert x,
usw.
Re: Größter Wert aus Spalte ausgeben
Verfasst: Montag 30. Januar 2012, 19:54
von nomnom
Nobuddy hat geschrieben:nomnom hat geschrieben:Wie meinst du das? Als Ergebnis kommt bei mir `['2', 'KOPIER-PAPIERE', '11']`. Ist das nicht, was du möchtest? Die Zeile mit der größten dritten Spalte inklusive Hauptgruppennummer.
JEIN, als Gruppierung soll Spalte 1 dienen.
Also von Hauptgruppennummer 1 den Maxwert x,
von Hauptgruppennummer 2 den Maxwert x,
von Hauptgruppennummer 3 den Maxwert x,
von Hauptgruppennummer 4 den Maxwert x,
usw.
Achso, ich dachte dein Beispiel in deinem Anfangspost wäre ein komplettes Beispiel gewesen. Dann musst du die Zeilen filtern: Alle Zeilen mit Hauptgruppe 1, 2, 3 etc. Für sowas gibt es die Funktion `filter`.
Code: Alles auswählen
filter(lambda x: int(x[0]) == 1, table) # alle Zeilen aus Hauptgruppe 1
# `table` muss natürlich vorgefiltert sein (es dürfen nicht
# die Zeilen mit den drei Minussen vorhanden sein.
Wobei der erste Parameter von `filter` wiederum eine Funktion ist, die auf jedes Element des im zweiten Parameter festgelegten Iterators (Tupeln, Listen, Wörterbücher, Generatoren) angewandt wird. Also auf jede Zeile. Wenn die Funktion `True` zurückgibt, wird das Element behalten, ansonsten wird das Element eben herausgefiltert.
Re: Größter Wert aus Spalte ausgeben
Verfasst: Dienstag 31. Januar 2012, 07:57
von Nobuddy
Hallo nomnnom,
Danke für Deine Hilfe, jetzt funktioniert es!
Ich habe das jetzt so umgesetzt:
Code: Alles auswählen
table_list = []
with open(uigruppen_path, 'r') as f:
reader = csv.reader(f, delimiter="\t")
for line in reader:
if line[0] != '---' and line[2] != '---':
table_list.append(line)
erg_list = []
y = 1
while True:
table = tuple(table_list)
try:
biggest = max(filter(lambda x: int(x[0]) == y, table))
erg_list.append(biggest)
y = y + 1
except ValueError:
break
print(biggest)
Jetzt wird zu jeder Hauptgruppe der Maximalwert ausgespuckt, genau so wie es sein sollte.
Grüße Nobuddy
Re: Größter Wert aus Spalte ausgeben
Verfasst: Dienstag 31. Januar 2012, 18:59
von Hyperion
Und nun passe die Namen noch mal an, so dass Du den Datentypen (hier ``list``) nicht im Namen drin stehen hast! Zudem gieße das jetzt endlich mal in Funktionen; beides habe ich Dir auf uu.de schon zig mal "angestrichen"
So, erster "Anschiss" hier im "richtigen" Forum zum Thema
PS: Ich bin ja erfreut, dass Du Dir meinen Rat zu Herzen genommen und Dich hier angemeldet hast; damit bin ich als Exlusivhelfer ein wenig entlastet

Re: Größter Wert aus Spalte ausgeben
Verfasst: Mittwoch 1. Februar 2012, 00:17
von bords0
Ungetesteter Versuch mit groupby, unter der Annahme, dass alle Untergruppen einer Gruppe direkt hintereinander kommen:
Code: Alles auswählen
from itertools import groupby, itemgetter
with open(uigruppen_path, 'r') as f:
reader = csv.reader(f, delimiter="\t")
table = ((int(l[0]), int(l[2])) for l in reader if l[0] != '---')
groups = (g for k, g in groupby(table, key=itemgetter(0)))
result = dict(max(g, key=itemgetter(1)) for g in groups)
print(result)
#oder:
print(sorted(result.items()))
(Gibt deine Lösung auch bei mehrstelligen Zahlen das richtige Ergebnis? Stringsortierung und numerische Sortierung sind ja verschieden.)
Re: Größter Wert aus Spalte ausgeben
Verfasst: Mittwoch 1. Februar 2012, 08:24
von Nobuddy
Hallo zusammmen,
poste hier mal das komplette Konstrukt, wie ich es jetzt einsetze.
Code: Alles auswählen
table_list = []
erg_list = []
verg_dict = {}
def get_num(filename):
with open(filename, 'r') as infile:
reader = csv.reader(infile, delimiter="\t")
for line in reader:
if line[0] != '---' and line[2] != '---':
table_list.append(line)
y = 1
while True:
table = tuple(table_list)
try:
biggest = max(filter(lambda x: int(x[0]) == y, table))
erg_list.append(biggest)
y = y + 1
except ValueError:
break
for items in erg_list:
if items[0] != '---':
verg_dict[items[0]] = items[2]
get_num(subgroupindex_path)
gruppenzaehler_dict = {}
daten_list = []
try:
with codecs.open(subgroupindex_path, "r") as ziel_file:
reader = csv.reader(ziel_file, delimiter="\t")
for line in reader:
try:
gruppenzaehler_dict[line[0], line[1]] = line[2]
a = (line[0], line[1], line[2])
daten_list.append(a)
except IndexError:
pass
except IOError:
pass
daten_list = sorted(set(daten_list))
zeile_list = []
x = 0
p = 1
for line in daten_list:
if verg_dict != {}:
w = verg_dict.get(line[0], line[2])
else:
w = ''
if w == '' and line[0] != '---' and line[2] == '---':
if line[0] in str(x):
p = p + 1
zeile = (line[0], line[1], p)
zeile_list.append(zeile)
else:
p = 1
zeile = (line[0], line[1], p)
zeile_list.append(zeile)
x = x + 1
else:
zeile = (line[0], line[1], line[2])
zeile_list.append(zeile)
zeile_list = sorted(set(zeile_list))
with open(subgroupindex_path, "w") as ziel_file:
writer = csv.writer(ziel_file, delimiter="\t")
writer.writerows(zeile_list)
daten_list = zeile_list
del zeile_list
zeile_list = []
if verg_dict != {}:
for line in daten_list:
if line[0] != '---' and line[2] == '---':
p = verg_dict.get(line[0], line[2])
p = int(p) + 1
zeile = (line[0], line[1], p)
zeile_list.append(zeile)
get_num(subgroupindex_path)
else:
zeile = (line[0], line[1], line[2])
zeile_list.append(zeile)
zeile_list = sorted(set(zeile_list))
try:
if zeile_list[0] != '':
with open(subgroupindex_path, "w") as ziel_file:
writer = csv.writer(ziel_file, delimiter="\t")
writer.writerows(zeile_list)
except IndexError:
pass
Bestimmt würdet Ihr das hier wesentlich kürzer fassen, aber ich kann nur meinem Kenntnisstand etwas entsprechend umsetzen. Alles andere ist ein Lernprozess, der nach und nach kommen wird.
Hyperion, dachte mir das schon ...
Das Konstrukt, habe ich in eine Funktion verpackt, bistimmt geht es auch kürzer, aber für mich übersichtlicher und noch besser erkennbar.
Das mit den Namenszusätzen, wie name_list oder name_dict, ist für mich noch wichtig, um dies besser erkennen zu können.
Oder kann es da Probleme geben?
bords0, werde dies mal testen!
Das ganze Konstrukt, hat folgende Abläufe sicher zu stellen:
Code: Alles auswählen
- existiert die Datei subgroupindex_path nicht
- anlegen und befüllen der Datei
- Gruppierung nach Spalte 1 (Hauptgruppen, 1 - 20)
- fortlaufender Zähler in Spalte 3 (Untergruppenindex) anlegen
- Ist der Hauptgruppe kein Wert zugeordnet, erhält dieser auch kein Untergruppenindex
- existiert die Datei subgroupindex_path
- überprüfen neuer Daten
- Gruppierung nach Spalte 1 (Hauptgruppen, 1 - 20)
- fortlaufender Zähler in Spalte 3 (Untergruppenindex) anlegen
- Ist der Hauptgruppe kein Wert zugeordnet, erhält dieser auch kein Untergruppenindex
- werden nachträglich der Hauptgruppe einen Wert zugewiesen
- Zuweisung Zähler fürUntergruppenindex
- nicht mehr existierende Daten
- werden aus Datei gelöscht
- gelöschter Index wird nicht mehr in der betreffenden Hauptgruppe vergeben
Re: Größter Wert aus Spalte ausgeben
Verfasst: Mittwoch 1. Februar 2012, 10:38
von BlackJack
@Nobuddy: Das mag syntaktisch eine Funktion sein, aber Funktionen veränder normalerweise keine Datenstrukturen, die nicht als Argumente übergeben wurden. Weil damit das Programm unübersichtlich wird. Man sieht nicht mehr was, wo verändert oder benutzt wird.
Wenn Namen nur innerhalb einer relativ kurzen Funktion verwendet werden, dann brauchst Du auch die Namenszusätze für die Typen nicht. Also mehr Quelltext in Funktionen stecken. Auf Modulebene sollten nur definitionen von Konstanten stehen, also Namen aus importen, Funktions- und Klassendefinitionen, und Namen die an Konstante Werte gebunden sind. Die Typ-Anhängsel bei den Namen werden dann zum Problem, wenn man den Typ ändert. Dann muss man nämlich auch überall denn Namen ändern.
Statt Typen an die Namen anzuhängen, solltest Du lieber Abkürzungen vermeiden. Namen sollen das Verständnis des Quelltextes erleichtern. `verg_dict` tut das für mich nicht. Und für Dich in einem halben Jahr wahrscheinlich auch nicht mehr.
Nochmal zurück zur Funktion: Da werden Daten an eine `table_list` angehängt, und die Funktion wird mehrfach aufgerufen und das anscheinen auch immer mit dem selben Argument. Ausserhalb der Funktion wird der Name `table_list` nicht verwendet. Soll das so sein? Das ist alles sehr verwirrend, und sieht für mich erst einmal falsch aus. Werte sollten Funktionen als Argumente betreten und als Rückgabewerte verlassen. Eine Funktion sollte ausser auf Konstanten auf nichts „einfach so” zugreifen.
Warum wird in `get_num()` ein Tupel aus `table_list` erstellt? Der Schritt ist unnötig.
Statt `filter()` könnte man hier `itertools.ifilter()` verwenden. Beziehungsweise ist das wahrscheinlich in der Form sowieso kaputt, denn das `max()` bezieht sich auf Zeichenketten und nicht auf Zahlen:
Die Abbruchbedingung für die Verarbeitung ist auch ziemlich undurchsichtig. Das scheint sich darauf zu verlassen, dass am Anfang der `table_list` die Elemente mit Werten sind, und dann noch welche folgen, bei denen zumindest beim ersten Element in der ersten Spalte keine Ziffernfolge steht. Das ist für meinen Geschmack etwas zu implizit und sollte schon beim Einlesen gelöst werden. Die Liste sollte nur Daten enthalten, mit denen man auch etwas anfangen kann.
Jetzt wird mir auch klar warum es nichts ausmacht, dass die Funktion mehrfach aufgerufen wird und `table_list` immer weiter wächst. Es werden trotzdem immer die selben Datensätze am Anfang der Liste verarbeitet und der ganze, immer grösser werdende Rest ignoriert. WTF…
Weiter lese ich in dem Quelltext jetzt mal nicht…
Re: Größter Wert aus Spalte ausgeben
Verfasst: Mittwoch 1. Februar 2012, 13:39
von Nobuddy
Hallo BlackJack,
Danke für Deine Kritik!
Ich kann mir vorstellen, daß für Jemand der in der Materie drin ist, Kopfschütteln und vielleicht auch Bauchschmerzen, bei meiner jetzigen Programmierweise bekommt.
Da liegt noch ein langer Weg vor mir, hoffe aber mit Eurer Unterstützung, dies zu schaffen.
Ich werde versuchen, die Kritikpunkte umzusetzen.
Grüße Nobuddy
Re: Größter Wert aus Spalte ausgeben
Verfasst: Mittwoch 1. Februar 2012, 18:05
von Nobuddy
Wäre das eine Funktion, so wie Du sie forderst?
Code: Alles auswählen
def get_write(filename, datenpool):
with open(filename, "w") as zielfile:
writer = csv.writer(zielfile, delimiter="\t")
writer.writerows(datenpool)
get_write(subgroupindex_path, neuedaten)
Re: Größter Wert aus Spalte ausgeben
Verfasst: Mittwoch 1. Februar 2012, 20:44
von BlackJack
@Nobuddy: Das wäre eine Funktion die keine Datenstrukturen verwendet, die nicht als Argument herein gekommen sind, ja. Allerdings ist der Name irreführend, denn bei `get_*` erwartet man einen Rückgabewert.