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

Gente, venho de um passado distante para agradecer pela ajuda de todos vocês e dizer que desisti disso aí, mas usei essas informações para atualizar e melhorar um projeto de monitoramento da perfuração de poços de petróleo e gás que temos aqui na agência.

Está no Github, caso sirva para ajudar alguém que esbarre com esse post. É um projeto em andamento, empacado numas coisas, mas tem aplicação de pandas (para tratar os dados) e requests (para baixar os dados): https://github.com/gaudarde/monitor-perf

:call_me_hand:

2 Curtidas

Olá amigos! Sou novo aqui no site e novo também na area de programação. Gostaria de uma ajuda se for possível. Estou tentando fazer uma leitura de arquivo access com extensão accdb usando o jupyter notebook. A intensão é desenvolver com pandas. Eu já consegui conexão mas não consigo ler com pd.read_access. Segue o código abaixo:

import pyodbc as pyo

conn_string = pyodbc.connect(r’Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=C:\Users\romilson\Desktop\SDC AcademY 2022\Dados\Estados.accdb;’)
cursor = conn.cursor()
cursor.execute(‘select * from Estados’)

for tab in cursor.fetchall():
print (tab)

dados = pd.read_access(r’C:\Users\romilson\Desktop\SDC AcademY 2022\Dados\Estados.accdb’)
print(dados.read())

erro:

Input In [798], in <cell line: 1>()
----> 1 dados = pd.read_access(r’C:\Users\romilson\Desktop\SDC AcademY 2022\Dados\Estados.accdb’)
2 print(dados.read())

File C:\Anaconda\lib\site-packages\pandas_init_.py:261, in getattr(name)
257 from pandas.core.arrays.sparse import SparseArray as _SparseArray
259 return _SparseArray
→ 261 raise AttributeError(f"module ‘pandas’ has no attribute ‘{name}’")

AttributeError: module ‘pandas’ has no attribute ‘read_access’

já tentei colocar pd.read_accdb sem sucesso também!