Daten von single-column format in multi-column Format konvertieren

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.
Antworten
HeyHo26
User
Beiträge: 3
Registriert: Samstag 9. Februar 2019, 14:03

Hallo,

ich habe ein "Problem" und zwar werden meine Daten für mehrere Messstellen und Zeitschritte in einer Spalte raus geschrieben, heißt Zeitschritt 1, alle Messstellen und deren Werte. Der nächste Zeitschritt wird dann direkt darunter geschrieben mit der Information der vergangenen Zeit. Ich hätte es aber gerne als eine m * t+1 Matrix, also mit den m verschiedenen Messstellen als erste Spalte und für jeden Zeitschritt t dann eine extra Spalte. Klar kann ich das auch alles händisch mit Excel umformatieren, aber ich dachte mit python könnte ich mir da ne Menge Zeit sparen.

Eine Dummy Input Datei, sieht in etwa so aus und ist tab getrennt:
Zeit 1.5
Messstelle Messwert
1 23
2 45
3 23

123423 45
Zeit 1.75
Messstelle Messwert
1 33
2 21
3 55
….

usw.

Ziel wäre dann sowas:
Messstelle 1.5 1.75 …
1 23 33 …
2 45 21 …
3 23 55 …



Mein aktueller Workaround ist, die Eingangsdatei nach jedem Zeitschritt zu splitten, diese Splits in eine seperate Datei schreiben, und diese Dateien jeweils in ein dataframe einzulesen und sie zu mergen. Bei sehr großen Datenmengen - wo meist auch die Excel Zeilenbeschränkung deutlich überschritten wird - ist dies aber sehr langsam und ineffizient, daher die Frage, ob es nicht was schnelleres gibt :)

Code: Alles auswählen

#File umkonvertieren
s = open("Input.dat").read()
s = s.replace('Zeit, '#\nMessstelle')# Raute als split marker setzen
s = s.replace('Messstelle	Messwert\n', '')
f = open("Input_h.dat", 'w') 
f.write(s)
f.close()

#Splitten zu mehreren Text Dateien
with open ("Input_h.dat") as fo:
    op=''
    start=0
    cntr=1
    for x in fo.read().split("\n"):
        if (x=='#'):
            if(start==1):
                with open (str(cntr)+'.txt','w') as opf:
                    opf.write(op)
                    opf.close
                    op=''
                    cntr+=1
            else:
                start=1
        else:
            if(op==''):
                op=x
            else:
                op=op+'\n'+x

    fo.close()

#löschen der Hilfsdatei
os.remove('Input_h.dat')

#Einlesen der Textdateien ins Dataframe
i=1
while i<cntr:
    df="df_"+str(i)
    #print(df)
    df=pd.read_csv(str(i)+'.txt', sep='\t', )
    #print(df.head())
    if i==1:
        df_summary=df
    elif i>1:
        df_summary=df_summary.merge(df, on="Messstelle", how="left" )
    #löschen der Hilfsdateien
    import os
    os.remove(str(i)+'.txt')
    i=i+1


Grüße und vielen lieben Dank im voraus!

P.S. Ich bin kein Informatiker oder Informatikstudent, ich versuche mir mit python autodidaktisch meine Datenanalyse zu vereinfachen, also nicht zu böse sein, wenn ich was falsch labele oder einen komplett schwachsinnigen Algorithmus verwende :)
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Habe mir mal diese Datei erzeugt
https://we.tl/t-o4YNEk6nCq
und dies hier auf die Schnelle gecodet

Code: Alles auswählen

import pandas as pd

df = pd.read_csv('messdaten.tsv', sep='\t', header=None, names=['Messstelle', 'Messwert'])
df.dropna(axis=0, how='any', inplace=True)

zeit = df.query('Messstelle=="Zeit"').Messwert.tolist()

df.drop(df[df['Messstelle'] == 'Zeit'].index, axis=0, inplace=True)
df.set_index('Messstelle', inplace=True)
print(df)

Code: Alles auswählen

            Messwert
Messstelle          
1               11.0
2               12.0
3               13.0
123423          14.0
1               21.0
2               22.0
3               23.0
123423          24.0
1               31.0
2               32.0
3               33.0
123423          34.0
1               41.0
2               42.0
3               43.0
123423          44.0

Code: Alles auswählen

# Habe auf die Schnelle keine Lösung um die Anzahl der Messtellen zu berechnen
# muss daher manuell vorgegeben werden
COUNT = 4

daten = pd.DataFrame(df.iloc[0:COUNT].Messwert.tolist(), columns=[zeit[0]], index=df.iloc[0:COUNT].Messwert.index)
for i in range(1, COUNT):
    daten[zeit[i]] = df.iloc[i*COUNT:(i+1)*COUNT].Messwert.tolist()

print(daten)

Code: Alles auswählen

            1.50  1.75  2.00  2.25
Messstelle                        
1           11.0  21.0  31.0  41.0
2           12.0  22.0  32.0  42.0
3           13.0  23.0  33.0  43.0
123423      14.0  24.0  34.0  44.0
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Du liest die Datei ›Input.dat‹ komplett in den Speicher, ersetzt dann ein bißchen was und schreibst die Daten in ›Input_h.dat‹, nur um exakt die selben Daten wieder zu lesen. Das Schreiben und Lesen kannst Du Dir also sparen. Wenn man Dateien mit dem with-Statement öffnet, braucht man kein close (das man wenn man es benutzt auch aufrufen sollte). Warum fehlt das beim ersten ›open‹? Und warum benutzt Du bei den ersten zwei ›open‹ kein ›with‹?
›if‹ ist keine Funktion, die Klammern also allesamt überflüssig.
Generell, man liest Dateien Zeilenweise, dann spart man sich Speicher und es ist auch klarer, dass man eine Zeilenweise aufgebaute Datei hat.
Die letzte while-Schleife wäre auch eine for-Schleife, um das mehrfache zusammenbauen der Dateinamen zu verhindern, würde man eine Liste anlegen, über die man dann iterieren kann.
Insgesamt sieht das mehr nach C aus, als nach Python.

Wenn die Daten schlecht mit pandas zu lesen sind, dann mach das doch mit einfachem Python:

Code: Alles auswählen

from collections import defaultdict
data = defaultdict(list)
with open("Input.dat") as lines:
    for line in lines:
        key, value = line.split()
        data[key].append(value)
del data['Messstelle']
Antworten