Erstmal ein herzliches Hallo an alle.
Ich habe folgendes Problem.
Ich habe eine Tabelle im Ascii Format mit folgender Formatierung:
T X Y Z I
1 6 7 8 9
2 6 7 8 9
3 6 7 8 9
4 6 7 8 9
4 6 7 8 9
5 6 7 8 9
5 6 7 8 9
Diese Tabelle muss ich in eine Multirow umkonstruieren.
Es sollte dann folgendermassen aussehen:
T X Y Z I X Y Z I
1 6 7 8 9
2 6 7 8 9
3 6 7 8 9
4 6 7 8 9 6 7 8 9
5 6 7 8 9 6 7 8 9
Das heißt, wenn der Wert von T aus einer Zeile mit dem der nächsten übereinstimmt, sollen die X, Y, Z und I Werte in eine Zeile hintereinander geschrieben werde.
Ich komm jedoch grad auf keine Idee, wie ich das umsetzen kann.
Ich hoffe ihr könnt mir helfen!
Vielen Dank im Vorraus für Eure Mühe
Mit freundlichn Grüßen
Simon
Multirow Ascii Tabelle erstellen
@Smuun: Ein Stichwort wäre `itertools.groupby()`. Ansonsten müsstest Du Dir halt überlegen wie man das Schritt für Schritt jemandem beschreiben würde der ein bisschen dumm ist — dem Rechner halt.
Können denn maximal zwei aufeinanderfolgende Zeilen den gleichen T-Wert haben?
Können denn maximal zwei aufeinanderfolgende Zeilen den gleichen T-Wert haben?
@Smuun: weil groupby nicht jedem gleich geläufig ist, hier mal das Beispiel:
Code: Alles auswählen
>>> k = [[1, 6, 7, 8, 9], [2, 6, 7, 8, 9], [3, 6, 7, 8, 9], [4, 6, 7, 8, 9], [4, 6, 7, 8, 9], [5, 6, 7, 8, 9], [5, 6, 7, 8, 9]]
>>> [list(itertools.chain((u,), *(w[1:] for w in v))) for u, v in itertools.groupby(k, lambda d: d[0])]
[[1, 6, 7, 8, 9], [2, 6, 7, 8, 9], [3, 6, 7, 8, 9], [4, 6, 7, 8, 9, 6, 7, 8, 9], [5, 6, 7, 8, 9, 6, 7, 8, 9]]
Mein erster Ansatz war, per 'groupby' zu zählen, wie oft, der gleiche Wert T vorhanden ist, und dann eine Schleife zu schreiben, in der einzelne Array erstellt werde, und ich die danach wieder als Tabelle zusammenfügen kann.
Doch leider hängt es bei mir an der Umetzung diese Arrays zu erstellen und wie ich den Array dann mit den Daten erweitere die denselben T wert haben
Mein Code sieht bisher so aus:
import pandas as pd
import numpy as np
from itertools import groupby
create_points()
Doch leider hängt es bei mir an der Umetzung diese Arrays zu erstellen und wie ich den Array dann mit den Daten erweitere die denselben T wert haben
Mein Code sieht bisher so aus:
import pandas as pd
import numpy as np
from itertools import groupby
Code: Alles auswählen
data = pd.read_table('/home/simon/test/test_spur.asc', header=None, sep="\s")
data.columns = columns=['X','Y','Z','S','I','R','T']
print(data)
t_value = np.array(data['T'])
x_value =np.array(data['X'])
y_value =np.array(data['Y'])
z_value =np.array(data['Z'])
i_value =np.array(data['I'])
def create_points():
for i in range(len(t_value)):
points=[t_value[i] + x_value[i] + y_value[i] + z_value[i] + i_value[i]]
return(points)
create_points()
@Smuun: Das ist eine nicht ganz unwichtige Randbedingung weil man dann ja die Kopfzeile gar nicht erstellen kann bevor man die kompletten Zeilen verarbeitet hat. Oder gibt es da eigentlich keine Kopfzeile in der Datei?
Dein Beispielcode ist komisch/ungünstig weil Du erst die ganzen Spalten in parallele Sequenzen aufteilst, nur um dann wider über einen Index `i` aus den parallelen Sequenzen die zusammengehörigen Werte zusammenfügst. Dann hätte man die gar nicht erst trennen müssen und wäre diesen unnötigen Index los. ``for i in range(len(sequence)):`` ist in Python ein „anti pattern”. Wenn man so eine Zeile schreibt, dann macht man fast sicher etwas falsch oder unnötig komisch/umständlich.
Kann man mit Pandas denn überhaupt Frames mit Zeilen unterschiedlicher Länge erstellen?
Dein Beispielcode ist komisch/ungünstig weil Du erst die ganzen Spalten in parallele Sequenzen aufteilst, nur um dann wider über einen Index `i` aus den parallelen Sequenzen die zusammengehörigen Werte zusammenfügst. Dann hätte man die gar nicht erst trennen müssen und wäre diesen unnötigen Index los. ``for i in range(len(sequence)):`` ist in Python ein „anti pattern”. Wenn man so eine Zeile schreibt, dann macht man fast sicher etwas falsch oder unnötig komisch/umständlich.
Kann man mit Pandas denn überhaupt Frames mit Zeilen unterschiedlicher Länge erstellen?
@Black Jack:
Die Tabelle kommt ohne Header. Als Trennzeichen wird ein Leerzeichen benutzt ("\s")
Das muss ich zum abspeichern auch wieder benutzen, da das Modul für die weitere Bearbeitung (SPDLib) unbedingt Leerzeichen als Trenner haben will.
Das mit dem auftrenne in Sequenzen war so ne Idee von mir. Hab bis jetzt immer nur mit "R" gecoded. Bin grade dabei Python zu lernen. Aber dass mein Weg bis jetzt komisch war/ist, habe ich auch schon bemerkt
Ich werde es jetzt gleich mal mit itertools probieren und bei weiteren Problemen nochmals hier posten.
Auf jeden Fall finde ich euren Support genial! Wie schnell hier Leute drauf reagieren!!! Einfach super!
Die Tabelle kommt ohne Header. Als Trennzeichen wird ein Leerzeichen benutzt ("\s")
Das muss ich zum abspeichern auch wieder benutzen, da das Modul für die weitere Bearbeitung (SPDLib) unbedingt Leerzeichen als Trenner haben will.
Das mit dem auftrenne in Sequenzen war so ne Idee von mir. Hab bis jetzt immer nur mit "R" gecoded. Bin grade dabei Python zu lernen. Aber dass mein Weg bis jetzt komisch war/ist, habe ich auch schon bemerkt
Ich werde es jetzt gleich mal mit itertools probieren und bei weiteren Problemen nochmals hier posten.
Auf jeden Fall finde ich euren Support genial! Wie schnell hier Leute drauf reagieren!!! Einfach super!
Noch eine Frage: Ich hab jetzt die Tabelle anders eingelesen:
Wie kann ich das nun machen, dass jeweils eine Zeile als Array gespeichert wird?
Code: Alles auswählen
data_table = open('/home/simon/test/test_spur.asc')
data=data_table.read()
@Smuun: Dateiobjekte sind Iteratoren über die Zeilen. Zum Lesen von CSV-Dateien gibt es in der Standardbibliothek das `csv`-Modul, denn Du willst ja nicht nur die Zeilen haben, sondern auch die Zeilen noch mal in Felder aufgretrennt.
Der Datentyp mit dem Du dann operierst sind Listen und keine Arrays.
Dateien sollte man auch wieder schliessen. Üblicherweise verwendet man das öffnen zusammen mit der ``with``-Anweisung, dann wird die Datei auf jeden Fall geschlossen wenn der ``with``-Block verlassen wird, egal aus welchem Grund.
Der Datentyp mit dem Du dann operierst sind Listen und keine Arrays.
Dateien sollte man auch wieder schliessen. Üblicherweise verwendet man das öffnen zusammen mit der ``with``-Anweisung, dann wird die Datei auf jeden Fall geschlossen wenn der ``with``-Block verlassen wird, egal aus welchem Grund.
Ich hätte da noch eine Frage.
Ich Lese meine ASCII Datei folgendermassen ein:
Jetzt ist das problem, das er mir die entstandenen Listen folgendermassen ausgibt:
['4589329.514 5436784.859 689.017 51 88 1 215248.851582'], ['4589329.728 5436785.093 690.513 40 4 1 215248.851586']]
Durch die Anführungszeichen, kann ich die einzelnen Elemente nicht per Index ansprechen.
Kann mir jemand helfen wie ich diese Anführungszeichen weg bekomme?
Ich Lese meine ASCII Datei folgendermassen ein:
Code: Alles auswählen
l=[]
with open("/home/simon/test/test_spur.asc") as f:
r = csv.reader(f, delimiter=",")
for row in r:
returns = [(row)]
l.extend(returns)
['4589329.514 5436784.859 689.017 51 88 1 215248.851582'], ['4589329.728 5436785.093 690.513 40 4 1 215248.851586']]
Durch die Anführungszeichen, kann ich die einzelnen Elemente nicht per Index ansprechen.
Kann mir jemand helfen wie ich diese Anführungszeichen weg bekomme?
Das einlesen hat jetzt super geklappt, und das sortieren funktioniuert auch. Nur schreibt er mir die Werte nach denen ich sortiert hab doppelt. Das sollte nicht sein.
Aber ich verstehe nicht so warum. Vielleicht hat nochmal jemand ne Idee:
Code sieht folgendermassen aus:
Wenn ich die Liste mit .append anlege, macht mir Python noch mehr Klammern und groupby fuktioniert nicht.
Die Ausgangsliste sieht so aus:
[['4589319.747', '5436773.357', '685.837', '49', '106', '1', '215248.851500']]
Sortiert werden soll wie oben in der Beispieltabelle aber hier nach dem Wert an 7. Stelle.
Also [6].
Sortierung mache ich folgendermaßen:
So erfolgt die Ausgabe so:
[['215248.851509', '5436774.450', '688.077', '55', '98', '1', '215248.851509'],
['215248.851513', '5436775.015', '687.611', '73' ,'81', '1', '215248.851513', '5436775.596', '683.714','57', '12', '2', '215248.851513']]
Aber sie sollte so aussehen:
[['215248.851509', '5436774.450', '688.077', '55', '98', '1'],
['215248.851513', '5436775.015', '687.611', '73' ,'81', '1', '5436775.596', '683.714','57', '12', '2']]
Auf jeden Fall schonmal vielen Dank!
Aber ich verstehe nicht so warum. Vielleicht hat nochmal jemand ne Idee:
Code sieht folgendermassen aus:
Code: Alles auswählen
l=[]
with open("/home/simon/test/test_spur.asc") as f:
r = csv.reader(f, delimiter=" ")
for row in r:
returns = [(row)]
l.extend(returns)
print(l)
Die Ausgangsliste sieht so aus:
[['4589319.747', '5436773.357', '685.837', '49', '106', '1', '215248.851500']]
Sortiert werden soll wie oben in der Beispieltabelle aber hier nach dem Wert an 7. Stelle.
Also [6].
Sortierung mache ich folgendermaßen:
Code: Alles auswählen
[list(itertools.chain((u,), *(w[1:] for w in v))) for u, v in itertools.groupby(l, lambda d: d[6])]
[['215248.851509', '5436774.450', '688.077', '55', '98', '1', '215248.851509'],
['215248.851513', '5436775.015', '687.611', '73' ,'81', '1', '215248.851513', '5436775.596', '683.714','57', '12', '2', '215248.851513']]
Aber sie sollte so aussehen:
[['215248.851509', '5436774.450', '688.077', '55', '98', '1'],
['215248.851513', '5436775.015', '687.611', '73' ,'81', '1', '5436775.596', '683.714','57', '12', '2']]
Auf jeden Fall schonmal vielen Dank!
Zuletzt geändert von Smuun am Dienstag 13. Januar 2015, 16:47, insgesamt 1-mal geändert.
@Smuun: Dieser Unsinn den Du da mit `extend()` und `returns` und den vielen selbstgeschriebenen Klammern machst hat den Effekt von einem einfachen `append()`. Wenn Du das nicht siehst, dann hast Du Listen, und `append()` und `extend()` nicht verstanden und solltest erst weitermachen bis Du verstanden hast was Du da machst. Das sieht irgendwie nach raten aus.
Wobei man den gleichen Effekt auch mit einem `list()` mit dem Reader-Objekt als Argument erreichen kann, also ohne eine Schleife schreiben zu müssen.
Und selbst das muss man nicht einmal machen weil das Reader-Objekt ja ein Iterartor über die einzelnen Datensätze ist und `groupby()` ein iterierbares Objekt als erstes Argument erwartet.
Die Zeile zum gruppieren müsstest Du auch *verstehen*, denn die ist für die Randbedingungen mit den ersten Beispieldaten und man muss die natürlich an die neue Situation anpassen. Du hast ja nur den Index für die Gruppierungsspalte geändert, aber nicht angepasst wie die Zeilen zusammengefasst werden.
Wobei man den gleichen Effekt auch mit einem `list()` mit dem Reader-Objekt als Argument erreichen kann, also ohne eine Schleife schreiben zu müssen.
Und selbst das muss man nicht einmal machen weil das Reader-Objekt ja ein Iterartor über die einzelnen Datensätze ist und `groupby()` ein iterierbares Objekt als erstes Argument erwartet.
Die Zeile zum gruppieren müsstest Du auch *verstehen*, denn die ist für die Randbedingungen mit den ersten Beispieldaten und man muss die natürlich an die neue Situation anpassen. Du hast ja nur den Index für die Gruppierungsspalte geändert, aber nicht angepasst wie die Zeilen zusammengefasst werden.
@BlackJack
Wie gesagt, hab ich bis jetzt immer mit "R" geschrieben. Mir fällt die Umstellung grade schwer.
Ich werd mal versuchen es ohne die Schleife hin zu bekommen.
Und mit Recht hast du festgestellt, dass ich die Groupby Zeile leider immer noch nicht ganz verstehe...
Danke dir für deine Hilfe. Wird jetzt eine lange Lesenacht bei mir...
Wie gesagt, hab ich bis jetzt immer mit "R" geschrieben. Mir fällt die Umstellung grade schwer.
Ich werd mal versuchen es ohne die Schleife hin zu bekommen.
Und mit Recht hast du festgestellt, dass ich die Groupby Zeile leider immer noch nicht ganz verstehe...
Danke dir für deine Hilfe. Wird jetzt eine lange Lesenacht bei mir...
So. Hab jetzt das einlesen und die Gruppierung nochmals überarbeitet.
Gehts das noch effizienter her vom Code, oder kann man das so lassen?
Für eine kurze Beurteilung wäre ich dankbar. Und nicht mit Kritik sparen!
Gehts das noch effizienter her vom Code, oder kann man das so lassen?
Code: Alles auswählen
import itertools
import csv
with open('/home/simon/test/test_spur.asc', 'rb') as f:
reader = csv.reader(f, delimiter=" ")
l = list(reader)
data=[list(itertools.chain((u,), *(w[0:4] for w in v))) for u, v in itertools.groupby(l, lambda d: d[5])]
temp = open(r'/home/simon/test/test_spur_done.asc', 'w')
writer = csv.writer(temp, dialect='space')
for row in data:
writer.writerow(row)
temp.close()
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Auf den schnellen Blick (ohne die Mechanismen zu verstehen):
- Zeile 6 ist obsolet, da ``reader`` (würde ich anders nennen!) bereits iterierbar ist und somit *direkt* an ``groupby`` übergeben werden kann. Insbesondere bei *großen* Daten wird Dein Code damit deutlich schneller.
- Wieso nutzt Du beim schreibenden Zugriff auf eine Datei *nicht* ``with``?
- Noch effizienter wäre es, wenn Du ``data`` nicht als Liste, sondern Generator-Ausdruck umschreibst. Damit könntest Du Lesen, Verarbeiten und Schreiben effizient vereinen, weil immer nur *ein* Objekt gelesen, bearbeitet und sofort geschrieben wird.
Ich würde mir also drei Funktionen schreiben: Eine zum Lesen (erwartet einen Dateinamen), die einen Iterator von Zeilen zurückliefert (yield!). Eine zum Verarbeiten, die einen Iterator von Zeilen erwartet und einen Iterator von bearbeiteten Objekten zurückliefert. Und schlussendlich eine zum Schreiben, die als Eingabe einen Iterator von bearbeiteten Objekten erwartet und einen Dateinamen.
Diese kannst Du dann so kombinieren:
Neben einer hübschen Gliederung ist Dein ``process_data`` damit unabhängig, *woher* die Daten stammen. Und auch it dem Ergebnis kannst Du andere oder zusätzliche Dinge anstellen, als nur das Schreiben. Dies erleichtert auch das Testen ungemein
- Zeile 6 ist obsolet, da ``reader`` (würde ich anders nennen!) bereits iterierbar ist und somit *direkt* an ``groupby`` übergeben werden kann. Insbesondere bei *großen* Daten wird Dein Code damit deutlich schneller.
- Wieso nutzt Du beim schreibenden Zugriff auf eine Datei *nicht* ``with``?
- Noch effizienter wäre es, wenn Du ``data`` nicht als Liste, sondern Generator-Ausdruck umschreibst. Damit könntest Du Lesen, Verarbeiten und Schreiben effizient vereinen, weil immer nur *ein* Objekt gelesen, bearbeitet und sofort geschrieben wird.
Ich würde mir also drei Funktionen schreiben: Eine zum Lesen (erwartet einen Dateinamen), die einen Iterator von Zeilen zurückliefert (yield!). Eine zum Verarbeiten, die einen Iterator von Zeilen erwartet und einen Iterator von bearbeiteten Objekten zurückliefert. Und schlussendlich eine zum Schreiben, die als Eingabe einen Iterator von bearbeiteten Objekten erwartet und einen Dateinamen.
Diese kannst Du dann so kombinieren:
Code: Alles auswählen
dump(process_data(load("in.csv")), "out.csv")
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert