Forum: PC-Programmierung Python: Zusammenfassen großer Listen


von Dennis S. (eltio)


Lesenswert?

Hallo zusammen,

ich habe eine sehr lange Liste (> 20.000 Zeilen aus CSV-Datei) der Form:
[10, 1, 1]
[12, 0, 36]
[14, 60, 69]
[16, 0, 42]
[18, 0, 17]
[10, 7, 5]
[12, 14, 8]
...

Dies wiederholt sich mit verschiedenen Werten. Was ich jetzt benötige 
ist eine Zusammenfassung von den Zeilen zu einer Zeile unter der 
Vorraussetzung, dass die Werte der Spalte 1 eindeutig sind.

Anders formuliert: Mache aus der Liste oben die folgende Zeile:
[10, 1, 1, 12, 0, 36, 14, 60, 69, 18, 0, 17]

Im Endeffekt muss ich mir fünf Zeilen nehmen, gucken ob in der ersten 
Spalte die Zahlen 10 bis 18 vorkommen und wenn ja diese in eine neue 
Liste kopieren mit neueListe.append(alteListe[0], alteListe[1], ...). 
Anschließend kommen die nächsten fünf Zeilen.

Nun habe ich verschiedene Probleme: Zum Einen kann es vorkommen, dass 
z.B. die 12 zwei mal hintereinander vorkommt. Zum Anderen: wie kann ich 
abfragen wann ich die alte Liste vollständig abgearbeitet habe?

Ich hoffe auf eure Hilfe!

Gruß
Dennis

von Klaus Maus (Gast)


Lesenswert?

Hi,

Dennis S. schrieb:
> ich habe eine sehr lange Liste (> 20.000 Zeilen aus CSV-Datei) der Form:
> [10, 1, 1]
> [12, 0, 36]
> [14, 60, 69]
> [16, 0, 42]
> [18, 0, 17]
> [10, 7, 5]
> [12, 14, 8]
> ...
>
> Dies wiederholt sich mit verschiedenen Werten. Was ich jetzt benötige
> ist eine Zusammenfassung von den Zeilen zu einer Zeile unter der
> Vorraussetzung, dass die Werte der Spalte 1 eindeutig sind.
>
> Anders formuliert: Mache aus der Liste oben die folgende Zeile:
> [10, 1, 1, 12, 0, 36, 14, 60, 69, 18, 0, 17]

Wo bleiben die Zeilen [10, 7, 5] und [12, 14, 8]?

Vielleicht was in die Richtung?
1
d = dict()
2
for line in csv:
3
  if line[0] not in d.keys(): d[line[0]] = list()
4
  d[line[0]] += line

Ach ja: Python ist ziemlich flott. 20k Zeilen sind auf einem halbwegs 
aktüllen Rechner eher pillepalle.

LG,
Klaus

von Dennis S. (eltio)


Lesenswert?

Klaus Maus schrieb:
> Wo bleiben die Zeilen [10, 7, 5] und [12, 14, 8]?
Die werden in die nächste Zeile geschmissen
[10, 1, 1, 12, 0, 36, 14, 60, 69, 18, 0, 17],
[10, 7, 5, 12, 14, 8, ....]

> Vielleicht was in die Richtung?
Gute Idee, schaue ich mir mal genauer an!

> Ach ja: Python ist ziemlich flott. 20k Zeilen sind auf einem halbwegs
> aktüllen Rechner eher pillepalle.
Damit wollte ich auch nur den Vorschlag ausschließen, das händisch zu 
machen! ;-)

Gruß Dennis

von adsf (Gast)


Lesenswert?

Beschreib dein Problem mal genauer (was ist mit den 5 Zeilen etc), dann 
kann man dir genauer helfen. Hört sich im Grunde aber nicht sehr schwer 
an.

von Dennis S. (eltio)


Lesenswert?

Der Beitrag von Klaus war schon recht hilfreich, aber ich versuche es 
nochmals zu formulieren:

Ich nenne die erste Spalte jetzt "ID". Es könnten die ID 10, 12, 14, 16 
und 18 auftreten, jedoch nicht zwangsläufig in der Reihenfolge und / 
oder gleich häufig (d.h. doppeltes Auftreten direkt hintereinander ist 
möglich, fehlen auch jedoch selten).

Grundsätzliches Ziel ist es eine Liste folgender Art zu bekommen:

1. Zeile beinhaltet das erste Auftreten aller ID inkl. "Daten"
2. Zeile beinhaltet das zweite Auftreten aller ID inkl. "Daten"
3. Zeile beinhaltet das dritte Auftreten aller ID inkl. "Daten"

Jedoch soll erst eine neue Zeile "angefangen" werden, wenn das Set 
komplett ist. Kommt also die Zeile mit der ID 12 zweimal vor, so wird 
das erste oder zweite Vorkommen (unwichtig) ignoriert und zunächst nach 
der 14 gesucht.

Sollte eine ID fehlen (bspw. die 14) soll das komplette Set verworfen 
werden.

"Startpunkt" des Algorithmus soll die ID 10 sein. Also etwas in die 
Richtung wie:
wenn ID = 10 dann füge Daten zur Liste hinzu,
wenn ID = 12 und ID 10 bereits in Liste, füge Daten von ID 12 hinzu,
wenn ID = 14 und ID 14 bereits in Liste, füge Daten von ID 14 hinzu,
...


Ist das verständlicher?

Gruß
Dennis

von adsf (Gast)


Lesenswert?

Tut das was du willst? (wenn Reihenfolge der IDs z.b. 10,14,12, ... ist 
wird die 14 ignoriert, da die 12 vorher fehlt. Richtig so?
1
def transform(lines, ids = [10,12,14,16,18]):
2
    "<addWhatItreallymeansHere> lines = input, ids = list of the occurring IDs (in order)"
3
    res = []
4
    id_index = 0
5
    for line in lines:
6
        if line[0] == ids[id_index]:
7
            res += line
8
        id_index += 1
9
        if id_index == len(ids)-1:
10
            yield res
11
            res = []
12
            id_index = 0
Da ich nicht weiß wie fit du in Python bist: das ist ein Generator, 
falls du wirklich eine Liste brauchst kannst du z.b. einfach 
list(transform(liste)) schreiben. Und tu dir den Gefallen und setze 
einen vernünftigen Funktionsnamen, transform heißt die nur weil ich 
keine Ahnung habe was sie eigentlich tun soll.

von adsf (Gast)


Lesenswert?

KORREKTUR: das id_index+=1 (Zeile 8) muss eins weiter eingerückt werden, 
da habe ich beim kopieren ausversehen einen TAB gelöscht scheinbar.

von adsf (Gast)


Lesenswert?

Sorry triplepost... Vorhin Klausur geschrieben, ich bin noch abgelenkter 
als ich dachte. Beim 2. if das -1 von len(ids)-1 noch weg...

von Dennis S. (eltio)


Lesenswert?

Hallo adsf,

vielen Dank schon mal! Ich habe in der Tat sehr wenig Python-Erfahrung 
und das Thema Generatoren ist mir völlig unbekannt...

Ich habe jetzt den Code von dir an den Kopf meiner Quelldatei gepastet. 
Den Aufruf mache ich wie ich es häufiger im Netz gefunden habe mit

for n in transform(dataSet):
    print n

Leider kommt keine Ausgabe... Was habe ich übersehen?

Gruß Dennis

von Dennis S. (eltio)


Lesenswert?

Mein Ansatz scheint zu funktionieren, ist aber vermutlich sehr dreckig 
programmiert..
1
new = []
2
print("!> Clustering data...")
3
maxData = len(dataSet) / 5 * 5
4
for n in range(0, maxData - 1):
5
    #print n
6
    if dataSet[n][2]    == 10 and \
7
       dataSet[n+1][2]  == 12 and \
8
       dataSet[n+2][2]  == 14 and \
9
       dataSet[n+3][2]  == 16 and \
10
       dataSet[n+4][2]  == 18:
11
        new.append([dataSet[n],  \
12
                        dataSet[n+1], \
13
                        dataSet[n+2], \
14
                        dataSet[n+3], \
15
                        dataSet[n+4]])
16
    else: continue
17
18
# create an additional file for debugging
19
with open("tmp_" + inputFile, 'wb') as f:
20
    writer = csv.writer(f, delimiter = delimOutput)
21
    writer.writerows(new)

von Robert L. (lrlr)


Lesenswert?

>Mein Ansatz scheint zu funktionieren

nein,



>Nun habe ich verschiedene Probleme: Zum Einen kann es vorkommen, dass
>z.B. die 12 zwei mal hintereinander vorkommt.


10, 12, 12, 14, 16, 18

lässt dein Programm KOMPLETT aus...

von Dennis S. (eltio)


Lesenswert?

Ja, dessen bin ich mir bewusst. Aber ich finde im Moment keine andere 
Möglichkeit und dies ist "besser" als ein unvollständiges Datenset.

Gruß
Dennis

von adsf (Gast)


Lesenswert?

Dennis S. schrieb:
> for n in transform(dataSet):
>     print n

Sollte gehen. Ich habe einfach deine Beispiel oben als Liste testweise 
reingefüttert und es kam was raus? also dataSet=[[10, 1, 1],[12, 0, 
36],[14, 60, 69],[16, 0, 42],[18, 0, 17],[10, 7, 5],[12, 14, 8]]

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.