Entfernen von Maxima aus einem Dataframe

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Lucs88
User
Beiträge: 4
Registriert: Dienstag 30. Juli 2019, 17:57

Hallo,

Ich bin neu in Pandas Welt und hätte eine Frage bezüglich dem Entfernen von Elementen aus einem Dataframe:

Ich habe ein Dataframe aus n Zeilen und m Spalten jeder Eintrag ist eine float Variable. Meine Aufgabe ist es pro Zeile das größte Element zu entfernen. Daraus resultiert ein Dataframe, welches weiterhin n Zeilen hat, aber nun (m-1) Spalten, z.B.

Dataframe1 = 1 2 5 6
3 4 2 1

Dataframe2 = 1 2 5 (Element 6 entfernt)
3 2 1 (Element 4 entfernt)

Mit numpy habe ich ein wenig Erfahrung. Hier habe ich das Dataframe als Matrix betrachtet und mit Schleifen und dem Stack Befehl gearbeitet. Nun ist es mir aber wichtig komplett ohne Schleifen zu arbeiten, da die Dimensionen n und m sehr groß werden können.

Hat jemand eine Idee? Vielen Dank schon mal!

P.S. Sorry dass ich hier kein Code präsentiert habe. Habe meinen Code auf der Arbeit gelassen :-(
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Lucs88: Das ist für `DataFrames` etwas ungünstig von der Organisation her, denn dadurch werden ja Werte zwischen den Spalten verschoben. Es ist bei Pandas soweit ich das sehe aber einfacher Werte aus einer Spalte (`Series`) zu entfernen. Und das Maximum müsste dann ja einzigartig sein, oder zumindest in allen Zeilen gleich oft vorkommen, damit am Ende alle Zeilen gleich breit sind.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
ThomasL
User
Beiträge: 1378
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Man könnte den Dataframe in ein Numpy Array wandeln und den dann transponieren um dann den max-Wert pro Spalte zu ermitteln. Sinnvoll?
Schau mal hier: https://stackoverflow.com/questions/473 ... alculation
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
Lucs88
User
Beiträge: 4
Registriert: Dienstag 30. Juli 2019, 17:57

Schon mal vielen Dank für eure Antworten
__blackjack__ hat geschrieben: Dienstag 30. Juli 2019, 18:29 @Lucs88: Das ist für `DataFrames` etwas ungünstig von der Organisation her, denn dadurch werden ja Werte zwischen den Spalten verschoben. Es ist bei Pandas soweit ich das sehe aber einfacher Werte aus einer Spalte (`Series`) zu entfernen. Und das Maximum müsste dann ja einzigartig sein, oder zumindest in allen Zeilen gleich oft vorkommen, damit am Ende alle Zeilen gleich breit sind.
Ja, das Maximum ist eindeutig für jede Zeile.
@__blackjack__ : Hättest du einen alternativ Vorschlag welchen Datentyp ich nehmen sollte?
Lucs88
User
Beiträge: 4
Registriert: Dienstag 30. Juli 2019, 17:57

ThomasL hat geschrieben: Mittwoch 31. Juli 2019, 06:17 Man könnte den Dataframe in ein Numpy Array wandeln und den dann transponieren um dann den max-Wert pro Spalte zu ermitteln. Sinnvoll?
Schau mal hier: https://stackoverflow.com/questions/473 ... alculation
Danke ThomasL. Allerdings löst diese Vorgehensweise nicht mein Problem. In deinem Link wird eine doppelte For-Schleife verwendet. Mir geht es darum Schleifen (sofern möglich) zu vermeiden
Lucs88
User
Beiträge: 4
Registriert: Dienstag 30. Juli 2019, 17:57

Hier ist meine numpy Lössung

Code: Alles auswählen

def updateIteratedDataSet(X_1, n, m):
	X_2 = np.zeros((n,m-1));
	for i in range(0,n):  
   		index = np.argmax(X_1[i,:]);
        	X_2[i,:] = np.hstack([X_1[i,0:index], X_1[i,index+1:m]]);     
    	return X_2
Ist es möglich mit pandas (Datframes oder ähnliches) diese Schleife zu umgehen?
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Lucs88: Ich wüsste so auf Anhieb nicht wie das gehen sollte.

Anmerkungen zum gezeigten Code: `m` und `n` als Argumente sind überflüssig, die Werte kann man ja von `X_1` ermitteln.

Eingerückt wird in Python mit vier Leerzeichen pro Ebene, nicht mit Tabs. Insbesondere mischt man die nicht, denn das ``return`` und die Zeile davor sehen zwar im Beitrag richtig eingerückt aus, sind es aber nicht! Genau wegen solcher Probleme: keine Tabs.

Namen werden klein_mit_unterstrichen geschrieben. Ausnahmen: Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Einbuchstabige und dann auch noch nummerierte Namen sind selten gute Namen.

Nach Kommas und um binäre Operatoren erhöhen Leerzeichen die Lesbarkeit.

Semikolons sind dazu da um Anweisungen voneinander zu trennen, nicht um sie abzuschliessen. Man kann zwar eine Anweisung von einer leeren Anweisung trennen, aber das macht keinen Sinn. Das Semikolon braucht man in Python nur sehr selten, weil für lesbaren Code die Richtlinie eine Anweisung pro Zeile gilt.

Schleifen über Indexwerte die per `range()` erzeugt werden sind in Python ein „anti pattern“. Man kann direkt über die Elemente von Sequenzen iterieren, ohne den Umweg über einen Index. Falls man *zusätzlich* eine laufende Zahl braucht, gibt es `enumerate()`, und wenn man ”parallel” über mehr als eine Sequenz iterieren will, gibt es `zip()`.

Den Index des grössten Elements kann man vor der Schleife für alle Zeilen des Arrays bestimmen.

Ungetestet:

Code: Alles auswählen

def update_iterated_dataset(data):
    height, width = data.shape
    result = np.zeros((height, width - 1))
    for max_index, row, result_row in zip(data.argmax(1), data, result):
        result_row[:] = np.hstack([row[:max_index], row[max_index + 1:]])
    return result
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Die Lösung ist mir ein bißchen zu gemischt. Auf der einen Seite erzeugst du ein leeres Array, das Du füllst, in der nächsten Zeile benutzt Du hstack um zwei Teile zusammenzusetzen.
Entweder nur das eine oder nur das andere:

Code: Alles auswählen

def update_iterated_dataset(data):
    height, width = data.shape
    result = np.zeros((height, width - 1))
    for max_index, row, result_row in zip(data.argmax(1), data, result):
        result_row[:max_index] = row[:max_index]
        result_row[max_index:] = row[max_index+1:]
    return result
oder

Code: Alles auswählen

def update_iterated_dataset(data):
    return np.vstack([
        np.hstack([row[:max_index], row[max_index + 1:]])
        for max_index, row in zip(data.argmax(1), data)
    ])
oder natürlich per Maske:

Code: Alles auswählen

def update_iterated_dataset(data):
    mask = data != data.max(1)[:,None]
    return data[mask].reshape(data.shape[0], -1)
Antworten