Seite 1 von 1

Elemente einer aus Listen bestehende Liste neu sortieren

Verfasst: Donnerstag 13. Juni 2019, 14:52
von Rotkehlchen
Hallo liebes Forum,
Ihr habt mir schon oft weitergeholfen und ich hoffe, dass das auch diesmal der Fall sein wird :)
Ich habe folgendes vor:
Aus ein paar Excel-Tabellen habe ich Daten ausgelesen und je eine Tabellenzeile als Liste in einer (zusammenfassenden) Liste gespeichert. Das sieht ungefähr so aus:

Code: Alles auswählen

data = [['Gruppe1', 'bewertet', 'kein Kommentar'], ['Gruppe4', 'nicht bewertet', 'kein Kommentar'], ...] 
Hierbei kommen manche Gruppen mehrfach vor, andere nicht. Mein Ziel ist es nun, die Ergebnisse jeder Gruppe zusammenzufassen, also z. B. so:

Code: Alles auswählen

summary = [['Gruppe1', '3 mal bewertet, 1 mal nicht bewertet', '4 mal kein Kommentar'], ['Gruppe2', '2 mal bewertet', 'Kommentar: Bewertung noch nicht abgeschlossen'], ...]
Insbesondere sollen also keine Dopplungen des jeweils ersten Listenelements (Gruppennummer) mehr auftreten, und die Anzahl der Bewertungen gleichnamiger Gruppen soll angegeben werden. Ist es überhaupt möglich, eine Liste so zusammenzufassen?

Vielen Dank für jede Hilfe!
Rotkehlchen

Re: Elemente einer aus Listen bestehende Liste neu sortieren

Verfasst: Donnerstag 13. Juni 2019, 15:00
von __deets__
Dazu gibt es die Funktion "itertools.groupby"

Code: Alles auswählen

from itertools import groupby

data = [
    ['Gruppe1', 'bewertet', 'kein Kommentar'],
    ['Gruppe4', 'nicht bewertet', 'kein Kommentar'],
    ['Gruppe1', 'nicht bewertet', 'alle doof ausser Mutti!'],
]


keyfunc = lambda entry: entry[0]

for key, entries in groupby(sorted(data, key=keyfunc), keyfunc):
    print(key)
    for entry in entries:
        print(entry)
Innerhalb der Eintraege kannst du dann wiederum mit anderen Mitteln aggregieren, wie zB collections.Counter fuer die Anzahl von Bewertung/nicht Bewertung etc.

Re: Elemente einer aus Listen bestehende Liste neu sortieren

Verfasst: Donnerstag 13. Juni 2019, 15:01
von __blackjack__
@Rotkehlchen: Das sieht mir nach einem Fall für ein `collections.defaultdict()` das Gruppennamen auf `collections.Counter`-Objekte abbildet, die Du entsprechend `update()`test.

Re: Elemente einer aus Listen bestehende Liste neu sortieren

Verfasst: Donnerstag 13. Juni 2019, 15:39
von Rotkehlchen
Danke für die schnellen Antworten!
Da ich die von __deets__ zuerst gesehen habe, habe ich damit einen (vorläufigen) Versuch gewagt:

Code: Alles auswählen

def sort_data(data):
  temp_summary = []
  summary = []
  keyfunc = lambda entry: entry[0]
  for key, entries in groupby(sorted(data, key = keyfunc),keyfunc):
    temp = [key]
    for entry in entries:
      temp.append(entry[1])
    temp_summary.append(temp)
  for listelement in temp_summary:
    a = str(listelement.count("bewertet")) + " mal bewertet"
    b = str(listelement.count("nicht bewertet")) + " mal nicht bewertet"
    summary.append([listelement[0], a, b])
  return summary
(Hierbei habe ich die Kommentarelemente mal weggelassen, ist ja mehr oder weniger das gleiche Prinzip wie bei den Bewertungen.)
Als Ergebnis bekomme ich z. B.:

Code: Alles auswählen

>>> summary[4]
['Gruppe5', '2 mal bewertet', '1 mal nicht bewertet']
Damit bin ich an sich schon zufrieden, aber der Code könnte wohl auch eleganter sein... danke jedenfalls für die Hilfe, vielleicht hat jemand noch einen Tipp :)

Re: Elemente einer aus Listen bestehende Liste neu sortieren

Verfasst: Donnerstag 13. Juni 2019, 16:16
von Sirius3
Eingerückt wird in Python immer mit 4 Leerzeichen pro Ebene, nicht 2.
Eine Liste, deren erstes Element etwas anderes bedeutet, als die restlichen, ist schlecht. Nimm statt dessen z.B. ein Tuple mit key und entry-Liste.
Warum heißen die Variablen temp und temp_summary? Bisher hatte ich nicht gesehen, dass es sich um Temperaturen handelt.
String stückelt man nicht mit + zusammen, sondern benutzt Stringformatierung. Hier würde man aber gar keine fertig formatierten Strings zurückliefern, sondern die Zahlenwerte, mit denen kann man besser weiterarbeiten. Erst bei der Ausgabe schön lesbare Strings umwandeln.

Re: Elemente einer aus Listen bestehende Liste neu sortieren

Verfasst: Montag 17. Juni 2019, 08:39
von Rotkehlchen
Hallo Sirius3,
war meine Voreinstellung in IDLE, darüber habe ich mir noch nie Gedanken gemacht...
Aber wie erstelle ich diese Tupel, schließlich kann ich da ja nichts mehr hinzufügen, so wie ich das letzte Woche mit meiner for-Schleife gemacht habe?
Mit temp meinte ich temporär, da ich diese Listen am Schluss nicht ausgeben lasse.
Okay, das mit den Strings habe ich auch erst mal nur zu meiner Kontrolle gemacht, ob das am Schluss alles so angeordnet ist, wie ich es brauche.
Danke für Deine Antwort!

Re: Elemente einer aus Listen bestehende Liste neu sortieren

Verfasst: Montag 17. Juni 2019, 09:53
von Sirius3
@Rotkehlchen: jede lokale Variable ist temporär. Das in den Namen zu schreiben, ist also unsinnig.
Du brauchst auch das Tuple nicht nachträglich zu ändern, weil Du es erst zum Schluß erzeugst, also erst eine entries-Liste, und dann diese zusammen mit dem key in ein Tuple:

Code: Alles auswählen

def sort_data(data):
    keyfunc = lambda entry: entry[0]
    groups = []
    for key, entries in groupby(sorted(data, key=keyfunc),keyfunc):
       evaluations = []
       for entry in entries:
           evaluations.append(entry[1])
       groups.append((key, evaluations))
    summary = []
    for key, evaluations in groups:
        a = evaluations.count("bewertet")
        b = evaluations.count("nicht bewertet")
        summary.append((key, a, b))
    return summary
das ganze könnte man auch noch in eine Schleife zusammenfassen:

Code: Alles auswählen

def sort_data(data):
    keyfunc = lambda entry: entry[0]
    summary = []
    for key, entries in groupby(sorted(data, key=keyfunc), keyfunc):
        evaluations = [entry[1] for entry in entries]
        a = evaluations.count("bewertet")
        b = evaluations.count("nicht bewertet")
        summary.append((key, a, b))
    return summary
oder statt groupby mit defaultdict:

Code: Alles auswählen

def sort_data(data):
    groups = defaultdict(list)
    for entry in data:
        groups[entry[0]].append(entry[1])
    summary = []
    for key, evaluations in groups.items():
        a = evaluations.count("bewertet")
        b = evaluations.count("nicht bewertet")
        summary.append((key, a, b))
    return summary

Re: Elemente einer aus Listen bestehende Liste neu sortieren

Verfasst: Montag 17. Juni 2019, 10:29
von Rotkehlchen
Wow, Sirius3, jetzt habe ich echt die Qual der Wahl!
Danke für die schnelle Antwort, das hat mir sehr weitergeholfen!
Und ja, ich bin nicht so kreativ mit den Variablennamen...