Numpy Arrays

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
thedome
User
Beiträge: 8
Registriert: Mittwoch 25. Februar 2015, 12:06

Hallo leute,

ich versuche gerade .txt files spaltenweise einzulesen mit der Funktion np.genfromtxt(). Eine der Spalten beinhaltet Zeitdaten im Format 'hh:mm:ss' als String. Mithilfe der Funktion np.core.defchararray.split(a,sep=':') habe ich die Zeit in 3 Teile aufgeteilt. Ouput sieht dann folgendermaßen aus:

Code: Alles auswählen

	a=
	array([['21', '46', '37'], ['21', '46', '42'], ['21', '46', '42'], ...,

	       ['09', '15', '37'], ['09', '15', '37'], ['09', '15', '37']], dtype=object)

	np.shape(a)=(1906,)
Da ich mathematische Operationen mit den Daten durchführen will, denke ich, dass ich das Array in Int formatieren muss.
Ich habe zwei Fragen:

1. Wieso ist das shape (1906,) und nicht (1906,3)?Wie kann ich das ändern?
2. Wie kann ich das Array in int Format formatieren?


Bin für jede Hilfe dankbar.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

np.core.defchararray.split liefert Dir ein Array von Python Objekten erkenntlich am dtype=object. Die Frage ist ja, was Du mit den Daten anfangen willst. Normalerweise konvertiert man per converters-Parameter die Uhrzeit gleich in Sekunden o.ä.
thedome
User
Beiträge: 8
Registriert: Mittwoch 25. Februar 2015, 12:06

Mir würde es reichen, wenn ich die Zahlen als int und nicht als String konvertiert bekomme. Ziel ist Zeitdifferenzen zu berechnen, sodass ich zwei Zeitdaten voneinander abziehen kann.
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@thedome: daher habe ich auch von einem Konverter geschrieben, z.B:

Code: Alles auswählen

def parse_time(time):
    hours, minutes, seconds = map(int, time.split(':'))
    return (hours * 24 + minutes) * 60 +seconds
thedome
User
Beiträge: 8
Registriert: Mittwoch 25. Februar 2015, 12:06

Das funktionert leider nicht...Nachdem ich die Zeitdaten eingelesen habe befinden Sie sich schon im Array. Sieht dann so aus:

Code: Alles auswählen

time=array(['21:46:37', '21:46:42', '21:46:42', ..., '09:15:37', '09:15:37',
       '09:15:37'], 
      dtype='<U8')
Wenn ich den map Befehl nutze, bekomme ich eine Fehlermeldung (Split habe ich durch die numpy split Funktion ersetzt):

Code: Alles auswählen

hours, minutes, seconds = map(int, np.core.defchararray.split(time,sep=':'))

*** TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'
Theoretisch könnte ich jetzt mit einer For Schleife jedes Element konvertieren...Fällt dir noch was eleganteres ein?
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@thedome: wie schon geschrieben mußt Du beim einlesen einen Konverter angeben:

Beispiel:

Code: Alles auswählen

data = numpy.genfromtxt(filename, converters={0: parse_time})
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@Sirius3: den TypeError bekommt man (bzw. ich habe ihn auch bekommen...), wenn man das mit `converters=...` macht. Der TypeError war zumindest weg, wenn man `time` von str nach Bytes wandelt. Getestet mit Python 3.4.

Allerdings benutze ich Numpy zu wenig, um zu sagen, ob das eine gangbare Lösung oder ein Würg-Around ist.

Gruß, noisefloor
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@noisefloor: Den TypeError, den thedome bekommt, stammt ja daher, dass er versucht ein numpy-Array mit Listen per map in ein int zu verwandeln, hat also gar nichts mit Bytes oder Strings zu tun. Und über die Python-Version wissen wir nichts.

Zu Deinem Problem: je nach dem, mit was Du genfromtxt fütterst, brauchst Du entweder ein time.split(b':') oder time.split(':').
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Zu Deinem Problem: je nach dem, mit was Du genfromtxt fütterst, brauchst Du entweder ein time.split(b':') oder time.split(':').
Stimmt, Danke für den Hinweis. Mit `time.split(b':')` funktioniert es wie gewünscht.

Gruß, noisefloor
thedome
User
Beiträge: 8
Registriert: Mittwoch 25. Februar 2015, 12:06

also irgendwie bekomme ichs nicht hin..ich habe jetzt folgendes gemacht:

Code: Alles auswählen

def parse_time(time):
    hours, minutes, seconds = map(int, time.split(b':'))
    return (hours * 24 + minutes) * 60 +seconds
    

time=np.genfromtxt(file,converters={0:parse_time},delimiter='\t',usecols=(1))


time=
array([ nan,  nan,  nan, ...,  nan,  nan,  nan])
und genau, die file lese ich als Bytestream ein. Ich verstehe allerdings die Funktion parse_time nicht. Warum verrechest du stunden, minuten und sekunden im return befehl?
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

@thedome: Du benutzt nur Spalte 1 setzt aber den Konverter für Spalte 0. Das macht keinen Sinn. Wahrscheinlich ist in Spalte 1 auch Deine Uhrzeit und nicht in Spalte 0, also:

Code: Alles auswählen

time = np.genfromtxt(file, converters={1:parse_time}, delimiter='\t', usecols=(1,))
Und wo soll ich Deiner Meinung nach sonst die Anzahl der Sekunden berechnen? Eine eigene Variable halte ich da für überflüssig.

PS: Und ich hoffe mal, Du ließt die Datei nicht mehrmals für verschiedene Spalten ein, wie in Deinem ersten Beitrag angedeutet, sondern alles Spalten auf einmal.
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@thedome:
Du wolltest doch die Uhrzeiten als Zahlwerte repräsentiert im Numpy-Array haben. Das leistet der hier vorgeschlagene Parser. Wäre es dir lieber, stattdessen Tupel in der Form (Stunden, Minuten, Sekunden) in das Array zu stecken? Dann würde ich aber eher die Einführung einer zweiten Dimension für das Array empfehlen, um den Speicherverbrauch zu reduzieren und um Numpy-interne Zugriffe zu vereinfachen. Mag sein, dass Numpy dies ohnehin von selbst entsprechend optimiert – so gut kenne ich Numpy nicht.
thedome
User
Beiträge: 8
Registriert: Mittwoch 25. Februar 2015, 12:06

@Sirius3: Danke, macht sinn. Es hat jetzt funktioniert, allerdings nur mit einem Array. Wenn ich die Spalten in mehrere Arrays einlesen möchte, bekomme ich eine Fehlermeldung. Damit beantworte ich auch schon deine Frage, ich möchte natürlich alle Spalten nur mit einem Befehl einlesen:

Code: Alles auswählen

time,col2,col3,col4,col5=np.genfromtxt(txt,converters={1:parse_time},delimiter='\t',dtype=None,usecols=(1,2,3,4,5),unpack=True)

->ValueError: too many values to unpack (expected 5)
Die Fehlermeldung erscheint komischerweise nur mit dem Converter, ohne funktioniert alles. Zur Info, ich benutze Python 3.4.4.

@snafu: Ursprünglich wollte ich stunden, minuten, sekunden in einer zweiten Dimension haben. Mir ist eben erst bewusst geworden, dass es viel besser ist, den Zeitstempel in Sekunden umzurechen :)
Sirius3
User
Beiträge: 17748
Registriert: Sonntag 21. Oktober 2012, 17:20

Was liefert denn genformtxt ohne unpack?
thedome
User
Beiträge: 8
Registriert: Mittwoch 25. Februar 2015, 12:06

genau das selbe -.-
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

zeigt doch mal 1-2 Zeilen des Ausgangsdatensatzes.

Gruß, noisefloor
Antworten