Filtros com Pandas, apply e lambda

Olá, pessoal.

Estou usando os dados do Comex Stat (importações e exportações, Ministério da Economia) para estudar Python e Pandas e surgiu uma dúvida sobre a melhor forma de filtrar o DataFrame para trabalhar apenas com determinadas famílias de produtos. Os dados:

image

Os bens são identificados pela nomenclatura comum do Mercosul (‘CO_NCM’) – no exemplo, precisava de todos os produtos da NCM 8541.40.XY.

Como são números inteiros, converti para string, testei os valores usando str.startswith e depois filtrei com pd.query. Qual a melhor forma de fazer esse filtro?

O código está assim:

df['teste'] = df['CO_NCM'].apply(str)
df['teste'] = df.teste.str.startswith('854140')
df = df.query('teste == True')

abs,

1 Curtida

Ao meu ver a melhor forma de fazer este filtro seria usando uma simples máscara.

Segue o passo a passo:

A coluna realmente é interpretada pelo Pandas automaticamente e recebe o type de int64.
Como você gostaria de transformá-la em string, o jeito mais fácil é invocando o método df.astype(), que recebe um tipo de dado como parâmetro, ou seja, df.astype(str) transforma determinada coluna em str, ou df.astype(float) transformaria tudo em float.
É importante prestar atenção nesse momento para não passar uma string para essa função (df.astype(“int”), com int cercado por aspas retorna erro).

A parte da máscara acontece na célula 6:


Aqui basta fazer a mesma comparação que você fez na sua segunda linha de código. O Pandas retorna uma Series cheia de Trues e Falses, que antes você armazenava na coluna teste, correto?
Ao colocar o nome do dataframe (df[df…])antes disso tudo você consegue selecionar automaticamente todos os elementos de determinada(s) coluna(s) que são True.

Neste momento você pode sobrescrever o df original:
df = df[df["CO_NCM"].str.startswith("854140")

Criar outro:
co_854140 = df[df["CO_NCM"].str.startswith("854140")

Etc…

1 Curtida

Olá

Há diversas maneiras de fazer a mesma coisa, e isso é uma das coisas legais de programar
Você usa o que achar mais fácil, elegante, simples de lembrar ou replicável
E essa percepção muda a cada dia

import pandas as pd

# você pode usar converters direto ao abrir
# no caso aqui nos códigos de identificação
ncm = pd.read_csv("dados/EXP_2019.csv",\
                              sep=';', \
                              encoding='latin_1', \
                              converters={'CO_NCM': lambda x: str(x),
                                          'CO_UNID': lambda x: str(x),
                                          'CO_PAIS': lambda x: str(x),
                                          'CO_VIA': lambda x: str(x),
                                          'CO_URF': lambda x: str(x)
                                         })

search ="854140"

# cria uma série booleana com True ou False em cada linha no dataframe
# a partir do que foi buscado em search
bool_series = ncm["CO_NCM"].str.startswith(search, na = False) 

# cria um novo dataframe a partir dessa marcação
ncm_mercosul = ncm[bool_series].copy()
1 Curtida

Como @reichaves mencionou, converters na leitura da base é realmente uma boa opção. Isso porque, quando a conversão rola logo na leitura do arquivo, você não terá de se preocupar com isso no futuro.

Uma alternativa interessante é usar dtype no read_csv (supondo que é um csv). Algo como:

import pandas as pd

# Lê csv com "CO_NCM" como str
df = pd.read_csv("arquivo,csv", dtype={"CO_NCM": str})

# Usa o recorte de "CO_NCM" com str começando com "854140"
slice = df[df["CO_NCM"].str.startswith("854140", na=False)]

Para mais info sobre dtype, a documentação de Pandas ajuda bastante: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

1 Curtida