Mam plik pd.DataFrame
utworzony przez analizę niektórych arkuszy kalkulacyjnych programu Excel. Kolumna zawierająca puste komórki. Na przykład poniżej przedstawiono dane wyjściowe dla częstotliwości tej kolumny, w 32320 rekordach brakuje wartości dla dzierżawcy .
>>> value_counts(Tenant, normalize=False)
32320
Thunderhead 8170
Big Data Others 5700
Cloud Cruiser 5700
Partnerpedia 5700
Comcast 5700
SDP 5700
Agora 5700
dtype: int64
Próbuję usunąć wiersze, w których brakuje dzierżawcy, jednak .isnull()
opcja nie rozpoznaje brakujących wartości.
>>> df['Tenant'].isnull().sum()
0
Kolumna ma typ danych „Obiekt”. Co się dzieje w tym przypadku? Jak mogę usunąć rekordy w przypadku braku najemcy ?
np.nan
kiedy możeszpd.np.nan
?df[df['Tenant'].astype(bool)]
(zakładając brak białych znaków - tylko pusty ciąg) jest szybszy niżdf.replace('', np.nan).dropna(subset=['Tenant'])
Pythonic + Pandorable:
df[df['col'].astype(bool)]
Puste ciągi są fałszywe, co oznacza, że możesz filtrować wartości logiczne w następujący sposób:
df = pd.DataFrame({ 'A': range(5), 'B': ['foo', '', 'bar', '', 'xyz'] }) df A B 0 0 foo 1 1 2 2 bar 3 3 4 4 xyz
df['B'].astype(bool) 0 True 1 False 2 True 3 False 4 True Name: B, dtype: bool df[df['B'].astype(bool)] A B 0 0 foo 2 2 bar 4 4 xyz
Jeśli Twoim celem jest usunięcie nie tylko pustych napisów, ale także ciągów zawierających tylko spacje, użyj
str.strip
wcześniej:df[df['B'].str.strip().astype(bool)] A B 0 0 foo 2 2 bar 4 4 xyz
Szybciej niż myślisz
.astype
jest operacją zwektoryzowaną, jest to szybsze niż wszystkie dotychczas prezentowane opcje. Przynajmniej z moich testów. YMMV.Oto porównanie czasu, dorzuciłem kilka innych metod, o których mogłem pomyśleć.
Kod porównawczy, w celach informacyjnych:
import pandas as pd import perfplot df1 = pd.DataFrame({ 'A': range(5), 'B': ['foo', '', 'bar', '', 'xyz'] }) perfplot.show( setup=lambda n: pd.concat([df1] * n, ignore_index=True), kernels=[ lambda df: df[df['B'].astype(bool)], lambda df: df[df['B'] != ''], lambda df: df[df['B'].replace('', np.nan).notna()], # optimized 1-col lambda df: df.replace({'B': {'': np.nan}}).dropna(subset=['B']), ], labels=['astype', "!= ''", "replace + notna", "replace + dropna", ], n_range=[2**k for k in range(1, 15)], xlabel='N', logx=True, logy=True, equality_check=pd.DataFrame.equals)
źródło
value_counts domyślnie pomija NaN, więc najprawdopodobniej masz do czynienia z „”.
Możesz więc po prostu je odfiltrować, np
filter = df["Tenant"] != "" dfNew = df[filter]
źródło
Jest sytuacja, w której komórka ma spację, nie możesz jej zobaczyć, użyj
df['col'].replace(' ', np.nan, inplace=True)
aby zastąpić białe znaki jako NaN, a następnie
df= df.dropna(subset=['col'])
źródło
Możesz użyć tej odmiany:
import pandas as pd vals = { 'name' : ['n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7'], 'gender' : ['m', 'f', 'f', 'f', 'f', 'c', 'c'], 'age' : [39, 12, 27, 13, 36, 29, 10], 'education' : ['ma', None, 'school', None, 'ba', None, None] } df_vals = pd.DataFrame(vals) #converting dict to dataframe
Spowoduje to wyświetlenie (** - podświetlanie tylko wybranych wierszy):
age education gender name 0 39 ma m n1 ** 1 12 None f n2 2 27 school f n3 ** 3 13 None f n4 4 36 ba f n5 ** 5 29 None c n6 6 10 None c n7
Aby usunąć wszystko, co nie ma wartości „edukacyjnej”, użyj poniższego kodu:
df_vals = df_vals[~df_vals['education'].isnull()]
('~' oznacza NIE)
Wynik:
age education gender name 0 39 ma m n1 2 27 school f n3 4 36 ba f n5
źródło