2016-04-06 17 views
1

Ich lade ein Pandas Dataframe, das viele Datentypen (geladen aus Excel) hat. Zwei bestimmte Spalten sollten Floats sein, aber gelegentlich gab ein Forscher einen zufälligen Kommentar wie "nicht gemessen" ein. Ich muss alle Zeilen löschen, in denen Werte in einer der beiden Spalten keine Zahl sind, und nicht numerische Daten in anderen Spalten beibehalten. Ein einfaches Anwendungsfall sieht wie folgt aus (die reale Tabelle mehrere tausend Zeilen hat ...)Verwenden von Pandas Filtern von nicht-numerischen Daten aus zwei Spalten eines Dataframe

import pandas as pd 

df = pd.DataFrame(dict(A = pd.Series([1,2,3,4,5]), B = pd.Series([96,33,45,'',8]), C = pd.Series([12,'Not measured',15,66,42]), D = pd.Series(['apples', 'oranges', 'peaches', 'plums', 'pears']))) 

, die in dieser Datentabelle ergibt:

A B C    D 
0 1 96 12    apples 
1 2 33 Not measured oranges 
2 3 45 15    peaches 
3 4  66    plums 
4 5 8 42    pears 

ich nicht klar bin, wie diese erhalten Tabelle:

Ich versuchte dropna, aber die Typen sind "Objekt", da es nicht numerische Einträge gibt. Ich kann die Werte nicht in Floats konvertieren, ohne entweder die gesamte Tabelle zu konvertieren oder eine Serie gleichzeitig auszuführen, die die Beziehung zu den anderen Daten in der Zeile verliert. Vielleicht gibt es etwas Einfaches, das ich nicht verstehe?

Antwort

1

Sie können erste Teilmenge erstellen mit Spalten B, C und applyto_numeric, ob all Werte notnull sind. Dann boolean indexing verwenden:

print df[['B','C']].apply(pd.to_numeric, errors='coerce').notnull().all(axis=1) 
0  True 
1 False 
2  True 
3 False 
4  True 
dtype: bool 

print df[df[['B','C']].apply(pd.to_numeric, errors='coerce').notnull().all(axis=1)] 
    A B C  D 
0 1 96 12 apples 
2 3 45 15 peaches 
4 5 8 42 pears 

Nächste Lösung Verwendung str.isdigit mit isnull und xor (^):

print df['B'].str.isdigit().isnull()^df['C'].str.isdigit().notnull() 
0  True 
1 False 
2  True 
3 False 
4  True 
dtype: bool 

print df[df['B'].str.isdigit().isnull()^df['C'].str.isdigit().notnull()] 
    A B C  D 
0 1 96 12 apples 
2 3 45 15 peaches 
4 5 8 42 pears 

Aber Lösung mit to_numeric mit isnull und notnull ist am schnellsten:

print df[pd.to_numeric(df['B'], errors='coerce').notnull() 
    ^pd.to_numeric(df['C'], errors='coerce').isnull()] 

    A B C  D 
0 1 96 12 apples 
2 3 45 15 peaches 
4 5 8 42 pears 

Timings:

#len(df) = 5k 
df = pd.concat([df]*1000).reset_index(drop=True) 

In [611]: %timeit df[pd.to_numeric(df['B'], errors='coerce').notnull()^pd.to_numeric(df['C'], errors='coerce').isnull()] 
1000 loops, best of 3: 1.88 ms per loop 

In [612]: %timeit df[df['B'].str.isdigit().isnull()^df['C'].str.isdigit().notnull()] 
100 loops, best of 3: 16.1 ms per loop 

In [613]: %timeit df[df[['B','C']].apply(pd.to_numeric, errors='coerce').notnull().all(axis=1)] 
The slowest run took 4.28 times longer than the fastest. This could mean that an intermediate result is being cached 
100 loops, best of 3: 3.49 ms per loop 
+0

Danke! Ich mag die erste Lösung mit Anwendung, Notnull, für Wartbarkeit. Es scheint zu funktionieren! Ich werde es einen Tag geben und sehen, ob irgendwelche Probleme auftauchen, oder wenn jemand mit einer noch einfacheren Lösung antwortet. – ZSG

Verwandte Themen