Eu tenho um pd.DataFrame
que foi criado analisando algumas planilhas do Excel. Uma coluna com células vazias. Por exemplo, abaixo está a saída para a frequência dessa coluna, 32320 registros têm valores ausentes para Locatário .
>>> 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
Estou tentando descartar linhas em que o inquilino está ausente, mas a .isnull()
opção não reconhece os valores ausentes.
>>> df['Tenant'].isnull().sum()
0
A coluna possui tipo de dados "Objeto". O que está acontecendo neste caso? Como posso descartar registros onde o inquilino está faltando?
np.nan
quando você pode fazerpd.np.nan
?df[df['Tenant'].astype(bool)]
(assumindo que não há caracteres de espaço em branco - apenas string vazia) é mais rápido do quedf.replace('', np.nan).dropna(subset=['Tenant'])
Pítônico + Pandorável:
df[df['col'].astype(bool)]
Strings vazias são falsas, o que significa que você pode filtrar por valores booleanos como este:
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
Se seu objetivo é remover não apenas strings vazias, mas também strings que contêm apenas espaços em branco, use
str.strip
antes:df[df['B'].str.strip().astype(bool)] A B 0 0 foo 2 2 bar 4 4 xyz
Mais rápido do que você pensa
.astype
é uma operação vetorizada, isso é mais rápido do que todas as opções apresentadas até agora. Pelo menos, pelos meus testes. YMMV.Aqui está uma comparação de tempo, acrescentei alguns outros métodos que poderia imaginar.
Código de benchmarking, para referência:
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)
fonte
value_counts omite NaN por padrão, então você provavelmente está lidando com "".
Então você pode apenas filtrá-los como
filter = df["Tenant"] != "" dfNew = df[filter]
fonte
Há uma situação em que a célula tem espaço em branco, você não consegue ver, use
df['col'].replace(' ', np.nan, inplace=True)
para substituir o espaço em branco como NaN, então
df= df.dropna(subset=['col'])
fonte
Você pode usar esta variação:
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
Isso produzirá (** - destacando apenas as linhas desejadas):
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
Portanto, para descartar tudo que não tem um valor de 'educação', use o código abaixo:
df_vals = df_vals[~df_vals['education'].isnull()]
('~' indicando NÃO)
Resultado:
age education gender name 0 39 ma m n1 2 27 school f n3 4 36 ba f n5
fonte