Mam następujący DataFrame

A       B       C
1.0     abc     1.0
abc     1.0     abc
-1.11   abc     abc

Mam mieszane datatypy (float i str). Jak mogę upuścić wartości <= -1 w column A.

Otrzymuję błąd, jeśli wykonam następujące czynności z powodu mieszanych danych

df['A'] = (df['A'] != "abc") & (df['A'] > -1)
TypeError: '>' not supported between instances of 'str' and 'int'

Jak mogę zmienić swój obiekt, aby zrobić abc a str i 1.0 a float, więc mogę:

(df['A'] != "abc") & (df['A'] > -1)

print(df['A'].dtype)
    -> object

Chciałbym oczekiwany wyjście

df = 

A       B       C
1.0     abc     1.0
abc     1.0     abc
NaN     abc     abc
3
g_altobelli 4 czerwiec 2018, 22:53

3 odpowiedzi

Najlepsza odpowiedź

Do tego problemu jest co najmniej kilka różnych podejść.

Loc + pd.to_numeric.

pd.DataFrame.loc akceptuje Seria Boolean, więc możesz obliczyć maskę przez {{ X1}} i podawaj do settera loc.

Uwaga Nie ma potrzeby określenia df['A'] != 'abc', ponieważ seria mask konwertuje te wartości do NaN.

mask = pd.to_numeric(df['A'], errors='coerce') < -1
df.loc[mask, 'A'] = np.nan

print(df)

     A    B    C
0    1  abc    1
1  abc    1  abc
2  NaN  abc  abc

Spróbuj / z wyjątkiem

Zobacz @ Jan's Solution. To rozwiązanie jest korzystne, jeśli spodziewasz się wartości numeryczne i tylko szukają alternatywnego leczenia w przypadkach krawędzi.

3
jpp 5 czerwiec 2018, 12:03

Potrzebujesz wskaźników wierszy, w których spełniony jest twój stan. Możesz konwertować serię do numerycznych, który zmieniłby ciąg do NaN, a następnie wyszukaj swój stan i po prostu wyjmij wiersz. Zauważ, że nie zapisujemy serii z NaN z powrotem do Dataframe.

ser = pd.to_numeric(df['A'], errors='coerce')
df.loc[df['A']!='abc'].drop(list(ser[ser<=-1].index))

Wynik:

    A   B   C
0  1.0  abc 1.0
0
harvpan 4 czerwiec 2018, 20:22

Możesz użyć małej funkcji konwersji wartości do numerów:

import pandas as pd, numpy as np

df = pd.DataFrame({
    'A': [1.0, 'abc', -1.11], 
    'B': ['abc', 1.0, 'abc'], 
    'C': [1.0, 'abc', 'abc']})

def change(value):
    try:
        v = float(value)
        if v < -1:
            value = np.nan
    except ValueError:
        pass
    return value

df['A'] = df['A'].apply(change)
print(df)

To daje

     A    B    C
0    1  abc    1
1  abc    1  abc
2  NaN  abc  abc
2
Jan 4 czerwiec 2018, 20:22