Nan aus der Liste entfernen

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
mickimick
User
Beiträge: 4
Registriert: Samstag 31. August 2013, 19:20

Hey,
ich habe eine Liste mit ein paar nan- Einträgen, also

Code: Alles auswählen

L=[1,nan,12,5,324,nan,93]
,
und zudem eine Liste die fünfmal so lang ist wie L, also

Code: Alles auswählen

T=[1,2,1,2,3,4,5,33,42,435,643,234,123,643,234,123,52,6,4,43,634,3234,35,12,786,43,754,85,35,6,4,2,1,6,53]
.
Wie ich die nan Einträge effizient aus der ersten Liste entferne ist mir klar.

Code: Alles auswählen

L=L[isnan(L)==False]
Jetzt möchte ich genauso effektiv die fünf Elemente aus T entfernen, die zu meinen nan aus der ersten Liste gehören. Also, wenn in der ersten Liste mein nan an Stelle 1 steht, möchte ich die Elemente 5-9 aus meiner Liste T entfernen.
Wie kann ich das effektiv machen??
Danke für eure Hilfe!
Benutzeravatar
sparrow
User
Beiträge: 4600
Registriert: Freitag 17. April 2009, 10:28

Keine Ahnung ob man das als LC zusammenfassen kann, aber ich würde mir überlegen, ob die Abbildung als zwei Listen für die Daten tatsächlich richtig ist. Ich würde ein dict machen, wobei der Schlüssel der Wert aus L ist und als Wert die Daten aus T, die dazu passen. Dann hätte man in den Daten auch gleich den entsprechenden Zusammenhang.

Was immer geht ist die Möglichkeit die Daten entsprechend Stück für Stück zu prüfen und dann die Listen zu bearbeiten:

Code: Alles auswählen

>>> L=[1,"nan",12,5,324,"nan",93]
>>> T=[1,2,1,2,3,4,5,33,42,435,643,234,123,643,234,123,52,6,4,43,634,3234,35,12,786,43,754,85,35,6,4,2,1,6,53]
>>> removes=[]
>>> for i, val in enumerate(L):
	if val == "nan":
		removes += range(i*5, i*5+5)

		
>>> for remove in removes[::-1]:
	del T[remove]

	
>>> T
[1, 2, 1, 2, 3, 643, 234, 123, 643, 234, 123, 52, 6, 4, 43, 634, 3234, 35, 12, 786, 4, 2, 1, 6, 53]
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

Hallo,

falls ich Dich richtig verstehe:

Code: Alles auswählen

>>> L = [1, 'nan', 12, 5, 324, 'nan', 93]
>>> T = [1, 2, 1, 2, 3, 4, 5, 33 ,42, 435 , 643, 234, 123, 643, 234, 123, 52, 6, 4, 43, 634, 3234, 35, 12, 786, 43, 754, 85, 35, 6, 4, 2, 1, 6, 53]
>>> index2remove = [index for index, elem in enumerate(L) if elem == 'nan']
>>> new_T = [t for index, t in enumerate(T) if index not in range(index2remove[0], index2remove[1] + 1)]
Falls `L` mehrere `nan` enthält, kannst Du ja statt der `new_T` LC eine Schleife machen...

mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

mickimick hat geschrieben: Jetzt möchte ich genauso effektiv die fünf Elemente aus T entfernen, die zu meinen nan aus der ersten Liste gehören.
Ich sehe hier in XY-Problem! Wieso sind das getrennte Strukturen (also *zwei* Listen), wenn die Daten zueinander in Beziehung stehen? Sinnvoller könnte es sein, die Daten von vornherein zusammen zu fassen. Dazu benötigen wir aber mehr Kontext.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

mickimick hat geschrieben:Wie ich die nan Einträge effizient aus der ersten Liste entferne ist mir klar.
Code:
L=L[isnan(L)==False]
Nein ist es nicht. Dein Code tut nicht was Du erwartest und liefert einen Fehler (falls L die Liste von oben ist), was man übringens mit der interaktiven Shell sehr schnell selbst rausfinden kann ;)

Code: Alles auswählen

>>> from math import isnan
>>> nan=float('nan')
>>> L=[1,nan,12,5,324,nan,93]
>>> filter(lambda x: not isnan(x), L)
[1, 12, 5, 324, 93]
Zu dem anderen Problem, soweit ich es verstanden habe:

Code: Alles auswählen

>>> T=[1,2,1,2,3,4,5,33,42,435,643,234,123,643,234,123,52,6,4,43,634,3234,35,12,786,43,754,85,35,6,4,2,1,6,53]
>>> [v for i,v in enumerate(T) if not isnan(L[i/5])]
[1, 2, 1, 2, 3, 643, 234, 123, 643, 234, 123, 52, 6, 4, 43, 634, 3234, 35, 12, 786, 4, 2, 1, 6, 53]
BlackJack

@mickimick: Wenn Du die `nan`-Werte wie gezeigt aus `L` entfernen kannst, dann ist `L` schon mal keine Liste sondern sehr wahrscheinlich ein Numpy-Array. Dann sieht die Darstellung aber auch nicht *so* aus, denn `nan` kann nur in Arrays mit Gleitkommazahlen vorkommen. Was auch schön gewesen wäre wenn die Länge der Arrays der beschreibung im Text entspräche, denn `T` ist in dem Beispiel gar nicht 5 mal so lang wie `L`.

Du weisst ja offensichtlich wie man einen Index für `L` erstellt. Obwohl das noch etwas kürzer ginge, denn statt die Elemente mit `False` zu vergleichen um sie zu negieren kann man auch den ``~``-Operator verwenden: ``~isnan(L)``. Ich gehe jetzt mal davon aus, dass `T` auch ein Array ist und keine Liste. Dann kann man dort doch einfach die Form in ein 2D-Array ändern, den gleichen Index wie für `L` verwenden und das Ergebnis wieder „flach klopfen”. Wobei sich hier auch die Frage stellt warum das eine eindimensionale Struktur ist wenn jeweils fünf aufeinanderfolgende Werte mit einem Wert aus `L` korrespondieren. Das ist umständlich und führt genau zu solchen Fragen wie in diesem Beitrag.

Also mal Schritt für Schritt entwickelt:

Code: Alles auswählen

In [24]: L
Out[24]: array([   1.,   nan,   12.,    5.,  324.,   nan])

In [25]: T
Out[25]: 
array([   1,    2,    1,    2,    3,    4,    5,   33,   42,  435,  643,
        234,  123,  643,  234,  123,   52,    6,    4,   43,  634, 3234,
         35,   12,  786,   43,  754,   85,   35,    6,    4,    2,    1,
          6,   53])

In [26]: idx = ~np.isnan(L)

In [27]: L[idx]
Out[27]: array([   1.,   12.,    5.,  324.])

In [28]: T.reshape((5, None))
Out[28]: 
array([[   1,    2,    1,    2,    3,    4,    5],
       [  33,   42,  435,  643,  234,  123,  643],
       [ 234,  123,   52,    6,    4,   43,  634],
       [3234,   35,   12,  786,   43,  754,   85],
       [  35,    6,    4,    2,    1,    6,   53]])

In [29]: T.reshape((5, None))[idx]
Out[29]: 
array([[   1,    2,    1,    2,    3,    4,    5],
       [ 234,  123,   52,    6,    4,   43,  634],
       [3234,   35,   12,  786,   43,  754,   85],
       [  35,    6,    4,    2,    1,    6,   53]])

In [30]: T.reshape((5, None))[idx].flatten()
Out[30]: 
array([   1,    2,    1,    2,    3,    4,    5,  234,  123,   52,    6,
          4,   43,  634, 3234,   35,   12,  786,   43,  754,   85,   35,
          6,    4,    2,    1,    6,   53])
Antworten