Mappe zwei dataframes

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Progressive
User
Beiträge: 16
Registriert: Dienstag 25. Juni 2019, 05:43

Hi,

es ist nicht wirklich wissenschaftlich aber ich vermute, dass sich eine entsprechende Möglichkeit in pandas verbirgt. Hoffe ich zumindest:

Ich habe zwei dataframes, beide jeweils 15998 x 61 und ich möchte aus dem einen Daten mithilfe der Daten des anderen auslesen.

Das zweite df besteht aus willkürlichen Werten mit einigen NaNs und
das erste df besteht nur aus willkürlichen Werten.

Ich möchte durch alle Zellen des ersten df iterieren und dabei prüfen ob die quasi-korrespondierende Zelle im zweiten df ein NaN ist, oder nicht. Wenn nicht, dann schreibe ich den Zellenwert raus und speicher es in ein beliebiges Objekt.
Aktuell mache ich das mti for-Schleifen und das dauert nicht nur Ewigkeiten, das überdauert wahrscheinlich die Zeitachse des Universums..
Da es aber prinzipiell ein recht banales Anliegen ist, muss es dafür sicherlich eine elegante Lösung geben. Vermutlich mittels pandas?
Ein Subset bzw. Subdataframe hilft mir nicht. Um es etwas nachvollziehbarer zu machen:

Betrachtet man die erste Spalte beider dfs (alle Spalten repräsentieren ein Gerät), dann sieht das bspw. wie folgt aus:

Code: Alles auswählen

1 81   41
2 36   37
3 77   45
4 99   NaN
5 75   51
6 73   68
7 93   64
8 84   42
9 37   14
10 83   16
11 16   NaN
12 17   NaN
13 62   15
Von Interesse sind für mich die Zeilen 5-10, denn ich benötige 5 aufeinanderfolgende Zeilen ohne NaN. Aus dem ersten df greife ich mir diese Werte heraus und speichere sie anderweitig, die dann für das entsprechende Gerät verwendet werden.

Jemand eine kluge Idee, wie man das schneller/eleganter umsetzen kann?
Prinzipiell ist Laufzeit nicht wichtig, aber es dauert mitunter schon so lange, dass es mich selber markant Arbeitszeit kostet. Hatte es ursprünglich mit einem dictionary versucht, aber da kann man nicht mal iterieren.. (bin in python erst ziemlich neu..).
Für jegliche Anregungen schonmal vielen Dank im voraus!
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Doch, ein dictionary sollte da das Mittel der Wahl sein. Denn nur so kannst du deinen lookup von O(n) auf O(1) reduzieren. Zeig mal wie du das einliest. Oder sind die beiden Dataframes gleich, und es geht dir nur um subsequente Eintraege ohne NaN? Dann geht das noch anders.
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Progressive: Also ich verstehe die Problemstellung nicht. Kannst Du das mal mit einem Beispiel machen, also Daten für beide DataFrames und was dann da als Ergebnis heraus kommen soll als DataFrame und warum/nach welchen Kriterien.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Progressive hat geschrieben: Dienstag 25. Juni 2019, 16:39 Hatte es ursprünglich mit einem dictionary versucht, aber da kann man nicht mal iterieren..
Doch, das kann man. Über die Schlüssel mit der keys()-Method und über die Werte mittels values(). Für die Schlüssel kann man den Aufruf von keys() auch weglassen und direkt über das Dictionary iterieren. Dann werden standardmäßig die Schlüssel benutzt. Bist du vielleicht darüber gestolpert...?
Progressive
User
Beiträge: 16
Registriert: Dienstag 25. Juni 2019, 05:43

__deets__ hat geschrieben: Dienstag 25. Juni 2019, 16:47 Doch, ein dictionary sollte da das Mittel der Wahl sein. Denn nur so kannst du deinen lookup von O(n) auf O(1) reduzieren. Zeig mal wie du das einliest. Oder sind die beiden Dataframes gleich, und es geht dir nur um subsequente Eintraege ohne NaN? Dann geht das noch anders.
Aber ein dictionary kann nur über "key" iterieren. Und ich habe 60 Geräte, deren Name ich nicht überall mitschleppen möchte..?

Das erste df lese ich mittel pd.read_csv() ein und das zweite ist die Ableitung des anderen.
__blackjack__ hat geschrieben: Dienstag 25. Juni 2019, 17:22 @Progressive: Also ich verstehe die Problemstellung nicht. Kannst Du das mal mit einem Beispiel machen, also Daten für beide DataFrames und was dann da als Ergebnis heraus kommen soll als DataFrame und warum/nach welchen Kriterien.
df2:
1 nan nan nan
2 0.00010210251852879604 0.0002834403248613282 2.288389780280911e-05
3 0.0013591085246769524 0.0010369422445753451 0.00011443615609185026
4 0.0011249694159122664 0.0010034914194550215 8.97855480435153e-05
5 0.0009577152903104819 0.0010334171576232565 nan
6 0.0009066640310461116 0.0008855385099498791 nan
7 0.0008027864687328856 0.0009805991881133291 nan
8 0.0006108984021605812 0.0006566828648440215 0.0005545720127763248
9 0.0005897728810644043 0.0008379956705598379 nan
10 0.000575689200333615 0.0007570186731272743 0.001779877236971851
11 0.0005545553456985236 0.0009348313925076901 0.001496436912110495
12 0.0004559779141218856 0.0007182927178870369 0.0013256576995565872
13 0.0004806118550924193 nan 0.0012974986716339024
14 0.0004119601616839885 nan 0.0011918793996918628
15 0.00045421120387637015 nan 0.0010703930696957173
16 0.0004278105526602932 nan 0.0008591295251949502
17 0.0004577279572896137 nan 0.0006707498784970095
18 0.00032745807729923915 nan 0.0004911871159488587
df1
1 1043394,1 2369745,9 334376,1
2 1044619,3 2366344,7 334101,5
3 1028310,4 2353901,7 332728,3
4 1014811,1 2341860,1 331650,9
5 1003318,8 2329459,4 95741,2
6 992439,1 2318833,2 308645,1
7 982805,9 2307066,3 527041,8
8 975475,3 2299186,3 520387,1
9 968398,2 2289130,6 494233,7
10 961490,1 2280046,6 472875,7
11 954835,6 2268828,9 454918,9
12 949364 2260209,6 439011,4
13 943596,8 135985,4 423441,8
14 938653,4 2449305 409139,6
15 933203 3656065 396295,2
16 928069,4 3531592,6 385985,9
17 922576,8 3339032,5 377937,1
18 918647,4 3199117,3 372043
D.h., ausgehend von df2, wo ich mir angucke, wo 5 Zeilen in einer Folge einer Spalte jeweils ohne NaN auftreten, suche ich zwei solcher Ereignisse und benutze mit diesen Indizes die korrespondierenden Werte in df1.

D.h., z.B. wären die Zeilen 2-6 der ersten Spalte von df2 interessant und würde daher dieselben Zeilen 2-6 der ersten Spalte von df1 benutzen und als Objekt speichern.
Vermutlich geht auch das eleganter aber mir wäre schon geholfen, wenn ich nicht solange durch die dfs iterieren müsste.
snafu hat geschrieben: Dienstag 25. Juni 2019, 18:09
Progressive hat geschrieben: Dienstag 25. Juni 2019, 16:39 Hatte es ursprünglich mit einem dictionary versucht, aber da kann man nicht mal iterieren..
Doch, das kann man. Über die Schlüssel mit der keys()-Method und über die Werte mittels values(). Für die Schlüssel kann man den Aufruf von keys() auch weglassen und direkt über das Dictionary iterieren. Dann werden standardmäßig die Schlüssel benutzt. Bist du vielleicht darüber gestolpert...?
Die keys sind in meinem Fall "101, 102, 103,.. 161". Soweit ich das sehe, kann man mit solchen keys nicht vernünftig drüber iterieren und v.a. nicht gezielt ein- und auslesen. Wenn ich beispielsweise durch die dfs iteriere, wo jede Spalte ein Gerät "101 - 161" repräsentiert, ist das m.E.n. äußerst umständlich mit einem dictionary.
Benutzeravatar
snafu
User
Beiträge: 6738
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Also geht es um die Bezeichnung der Schlüssel? Die kannst du in read_csv() mit dem names-Parameter beim Einlesen festlegen.
Progressive
User
Beiträge: 16
Registriert: Dienstag 25. Juni 2019, 05:43

snafu hat geschrieben: Mittwoch 26. Juni 2019, 07:14 Also geht es um die Bezeichnung der Schlüssel? Die kannst du in read_csv() mit dem names-Parameter beim Einlesen festlegen.
Schlüssel = keys?
Die keys sind mir prinzipiell egal, ich hatte nur ursprünglich es über ein dict versucht - aber das kann man ja nicht indizieren..

Aktuelle suche ich eher nach einer effizientieren Methode, die irgendwie zwei data frames vergleicht und als Result/Bedingung Daten aus dem einen df ausgibt.
Benutzeravatar
__blackjack__
User
Beiträge: 13077
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Progressive: So richtig schlauer bin ich immer noch nicht. Die Werte für df1 und df2 sind keine vollständigen DataFrames, oder? Da fehlt mindestens der Spaltenindex. Und Du sprichst von NaNs in der ersten Spalte, nur besteht die erste Spalte in beiden DataFrames aus den ganzen Zahlen 1 bis 18. Oder ist das nicht die erste Spalte sondern der Zeilenindex? Falls ja, warum gibst Du *den* an, den Spaltenindex aber nicht?

Was sind ”Ereignisse” und wo kommen plötzlich *zwei* davon her?

”[A]ls Objekt speichern” ist auch etwas das etwas schwammig ist, denn letztlich ist in Python jeder Wert ein Objekt, also auch jeder wird als Objekt im Speicher.

Du suchst nach einer effizienteren Methode „die irgendwie zwei data frames vergleicht“ – ja aber *wie*. Solange Du nicht präzise die Eingabedaten, die Kriterien für die Auswahl, und die Ausgabedaten beschreibst, kann man nicht wirklich helfen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Progressive
User
Beiträge: 16
Registriert: Dienstag 25. Juni 2019, 05:43

Mh, ich kann Beiträge scheinbar nicht editieren?

Der Spaltenindex lautet einfach "Gerät1", "Gerät2", "Gerä.."..
df2 ist die Ableitung von df1

Ereignisse sind "Situationen", in denen eine Spalte mindestens fünf Zeilen in einer Folge ohne NaNs aufweist. Von denen benötige ich zwei pro Spalte/Gerät.

Etwas als Objekt speichern ist natürlich vage, ich habe es an C++ angelehnt und mir in python eine Klasse angelegt, damit ich das <irgendwie> gewohnt strukturieren kann.
Ein Objekt ist letztlich pro Gerät ein Konstruktor einer Klasse und dort speichere ich diese zwei Ereignisse jeweils ab. Heißt, ich kann einem Gerät jeweils zwei Ereignisse zuweisen und abrufen. Ich weiß nicht, wie man das hätte klüger machen können?

Kritierium ist:

Prüfe in df2, ob fünf aufeinanderfolgenden Zeilen kein NaN aufweisen. Wenn dem so ist, nutze die korrespondierenden Zeilen-/Spaltenindizes in df1 und extrahiere diese (fünf) Werte.
Das wird als Ereignis gespeichert und geschieht pro Spalte/Gerät zweimal.

Ist das nachvollziehbar? Ich kann das bei Gelegenheit auch visualisieren :)
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn das alles ist, dann kommst du um N*M fuer N=Anzahl der Zeilen, M=Anzahl der Spalten an Operationen nicht herum. Immer noch linear, da ich mal annehme die M sind mehr oder minder fix. Wenn das fuer dich von der Laufzeit nicht linear, sonder anders ansteigt, dann hast du was falsch programmiert. Wenn du lineare Zeitanstiege misst, aber dir das zu langsam geht, dann musst du schauen, ob du optimiertere Funktionen in Pandas findest, um sowas effizienter zu machen. Ggf. zb groupby.
Sirius3
User
Beiträge: 17739
Registriert: Sonntag 21. Oktober 2012, 17:20

Ich bin immer wieder überrascht, dass Pandas auch schon für die auf den ersten Blick seltsamen Anwendungsfälle hat:
https://pandas.pydata.org/pandas-docs/s ... ling.count
Damit einfach schauen, wo ein Wert 5 erreicht wird und schon hast Du einen Index um auf Dein df1 zuzugreifen.
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Mir ist das viel zu viel... ich hab's ja lieber komponierbar. Aber der Anspruch ist da ein anderen, und beeindruckend ist's in jedem Fall.
Progressive
User
Beiträge: 16
Registriert: Dienstag 25. Juni 2019, 05:43

Sirius3 hat geschrieben: Mittwoch 26. Juni 2019, 14:25 Ich bin immer wieder überrascht, dass Pandas auch schon für die auf den ersten Blick seltsamen Anwendungsfälle hat:
https://pandas.pydata.org/pandas-docs/s ... ling.count
Damit einfach schauen, wo ein Wert 5 erreicht wird und schon hast Du einen Index um auf Dein df1 zuzugreifen.
Yeah, genau danach habe ich gesucht. Danke!
Wie findet man sowas??

Jetzt muss ich alles umschreiben.. :mrgreen: :roll:
Antworten