2
respostas

[Dúvida] Projeto paralelo

Olá, estou praticando o uso do pandas. Tenho dois DataFrames, exemplo: df_candidato:

-CANDIDATOINSTITUICAO
0MARCOS AFONSOUFBA
1MARIO AUGUSTOUNEMAT
2PEDRO HENRRIQUEIFBA

df_resultado

-CANDIDATONOTA
0MARIO9.0
1PEDRO16.0
2MARCOS13.0

-- Quero criar uma coluna NOTA no dataframe df_candidato, onde os nomes (parte dos nomes) coincidirem, os nomes não seguem uma ordem. apliquei o filtro:

df_candidatos['CANDIDATO'].apply(lambda x: df_resultado['NOTA'][df_resultado['CANDIDATO'].str.contains(x)])

e obtive o resultado:

Column 1Column 2Column 3
013.0NaNNaN
1NaN9.0NaN
2NaNNaN16.0

O dataframe resultante vem com deslocamento de linha e coluna. A correspondência do índice do df_candidatos está ok... Como evito isso, gostaria que as notas ocupassem apenas uma coluna, como no exemplo.

Column 1
013.0
19.0
216.0
2 respostas

Oi, Kleison, tudo bem?

O problema que você está enfrentando é que a função apply está retornando uma série para cada nome, em vez de um único valor. Uma solução para esse problema é utilizar o código abaixo:

# Extrair o nome do candidato do DataFrame df_candidato
df_candidato['NOME'] = df_candidato['CANDIDATO'].str.split().str[0]

# Mesclar os DataFrames com base no nome do candidato
df_final = df_candidato.merge(df_resultado, left_on='NOME', right_on='CANDIDATO', how='left')

# Descartar colunas intermediárias e renomear
df_final.drop(columns=['CANDIDATO_x', 'NOME'], inplace=True)
df_final.rename(columns={'CANDIDATO_y': 'CANDIDATO', 'NOTA': 'NOTA'}, inplace=True)

print(df_final)

Vamos explicar cada uma das linhas:

  • df_candidato['NOME'] = df_candidato['CANDIDATO'].str.split().str[0]: nesta linha, você está adicionando uma nova coluna chamada 'NOME' ao DataFrame df_candidato. Essa coluna é preenchida com o primeiro nome do candidato, que é extraído da coluna 'CANDIDATO'. O método str.split() divide o conteúdo da coluna 'CANDIDATO' em palavras com base nos espaços em branco, e .str[0] pega o primeiro elemento da lista resultante, que é o primeiro nome do candidato.

  • df_final = df_candidato.merge(df_resultado, left_on='NOME', right_on='CANDIDATO', how='left'): nesta linha, você está mesclando os DataFrames df_candidato e df_resultado com base nas colunas 'NOME' do DataFrame df_candidato e 'CANDIDATO' do DataFrame df_resultado. A opção how='left' indica que você deseja realizar uma junção à esquerda, o que significa que todos os registros do df_candidato serão mantidos, e apenas os registros correspondentes no df_resultado serão incluídos na junção.

  • df_final.drop(columns=['CANDIDATO_x', 'NOME'], inplace=True): nesta linha, você está removendo duas colunas do DataFrame df_final. As colunas 'CANDIDATO_x' e 'NOME' são descartadas. O argumento inplace=True faz com que as alterações sejam feitas diretamente no DataFrame, sem a necessidade de atribuir o resultado de volta a df_final.

  • df_final.rename(columns={'CANDIDATO_y': 'CANDIDATO', 'NOTA': 'NOTA'}, inplace=True): nesta linha, você está renomeando duas colunas no DataFrame df_final. A coluna 'CANDIDATO_y' é renomeada para 'CANDIDATO', e a coluna 'NOTA' é renomeada para 'NOTA'. Mais uma vez, o argumento inplace=True indica que as alterações devem ser feitas diretamente no DataFrame.

  • print(df_final): finalmente, você está imprimindo o DataFrame resultante após todas as operações de mesclagem, eliminação de colunas intermediárias e renomeação.

O resultado utilizando o código acima é uma tabela que traz a instituição, o nome do candidato e a nota:

Imagem de uma tabela com a universidade, candidato e nota

Todavia, vale ressaltar que como não tenho acesso ao cenário completo do projeto outros testes terão de ser feitos a fim de obter o resultado esperado, mas espero que esta resposta seja um bom ponto de partida para a resolução do seu problema.

Abraços!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓. Bons Estudos!

Bacana Rodrigo, obrigado pela rápida resposta. Interessante a solução, que solucionaria esse caso mas os dados utilizados no exemplo é fictício. Nos dados reais existem muitos casos em que o primeiro nome e até alguns sobrenomes coincidem. Como são dados públicos, não vejo problema em apontá-los, são a lista de inscritos e aprovados do ENA24 do profnit (profnit.org.br).

Analisando o DataFrame resultante desse código:

df_candidatos['CANDIDATO'].apply(lambda x: df_resultado['CANDIDATO1'].str.contains(x))

Resultado:

Identifiquei que quando há match nos nomes nos dois dataframes, ele trás um True... onde a linha corresponde ao índice de uma das tabelas e o número da coluna corresponde ao índice da outra tabela. Seria possível a partir desse resultado criar uma função que percorra esse dataframe e crie outro dataframe retornando em uma coluna o número da linha "True" e o número da coluna também com "True" em outra coluna, segue exemplo:

índice AÍndice B
03
14
25
36
. . .

sei que existe uma função que retorna o índice da linha. 'index.value'. Mas estou com dificuldade para pegar o número da coluna também.