Boa noite pessoal! Estou precisando de uma ajuda em algo simples, mas não estou conseguindo resolver.
Eu tenho dois dataframes, df1 e df2.
No df1, tenho uma coluna de ceps de 8 dígitos.
No df2, tenho uma coluna com cidade, outra com estado, outra com o cep de início da faixa de ceps da cidade e a última coluna com o cep do fim da faixa.
Preciso verificar cada cep do df1, em qual faixa de ceps do df2 se encaixa e copiar a cidade é o estado do df2 para o df1.
O objetivo aqui é preencher o df1 com mais duas colunas de cidade e estado.
Como o df1 tem mais de 600 mil linhas e o df2 mais de 11 milhões de linhas, preciso fazer de uma forma vetorizavel.
Já tentei usar loop For mas demora demais e não termina. Já tentei utilizar mutate( ifelse()) mas ultrapassa a memória.
Alguém de vocês poderia me ajudar, por favor?
Muito obrigado!!!
Eu nao testei as velocidades, mas acho que as três maneiras abaixo, alguma deve dar legal! Veja se resolve.
library(tidyverse)
# gera dados de brinquedo ------------------------
df1 <- data.frame(
cep = c("11001-000", "06001-000")
)
df2 <- data.frame(
cidade = c("sao paulo", "osasco"),
estado = c("sp", "sp"),
cep_ini = c(11000, 6000),
cep_fim = c(11999, 6299)
)
# dataprep ----------------------------------------
# extrai os primeiros 5 digitos do cep
df1 <- df1 %>%
mutate(
primeiros_5_digitos_do_cep = as.numeric(substr(cep, 1, 5))
)
# usando fuzzyjoin + tidyverse --------------------
library(fuzzyjoin)
df1 %>%
fuzzy_left_join(
df2,
by = c("primeiros_5_digitos_do_cep" = "cep_ini", "primeiros_5_digitos_do_cep" = "cep_fim"),
match_fun = list(`>=`, `<=`)
) %>%
select(-primeiros_5_digitos_do_cep, -cep_ini, -cep_fim)
#> cep cidade estado
#> 1 11001-000 sao paulo sp
#> 2 06001-000 osasco sp
# usando sqldf --------------------
library(sqldf)
sqldf("
SELECT cep, cidade, estado
FROM df1
LEFT JOIN df2 ON primeiros_5_digitos_do_cep BETWEEN cep_ini and cep_fim
")
#> cep cidade estado
#> 1 11001-000 sao paulo sp
#> 2 06001-000 osasco sp
# usando data.table ---------------
library(data.table)
df1dt <- as.data.table(df1)
df2dt <- as.data.table(df2)
setkey(df2dt, cep_ini, cep_fim)
foverlaps(
df1dt %>% mutate(primeiros_5_digitos_do_cep2 = primeiros_5_digitos_do_cep),
df2dt,
by.x = c("primeiros_5_digitos_do_cep", "primeiros_5_digitos_do_cep2"),
by.y = c("cep_ini", "cep_fim")
) %>%
select(-primeiros_5_digitos_do_cep, -cep_ini, -cep_fim)
#> cidade estado cep primeiros_5_digitos_do_cep2
#> 1: sao paulo sp 11001-000 11001
#> 2: osasco sp 06001-000 6001
Created on 2020-12-10 by the reprex package (v0.3.0)
eu usei esse post como referência:
Olá Athos, bom dia!!!
Muito obrigado pela sua resposta!!! Inicialmente eu tentei utilizar a solução número 1 que você enviou e apesar de ela parecer bem interessante, para mim começou a apresentar erro de vetor e etc… Como eu estava com pouco tempo para debugar, construí baseado na sua solução 2 com o sqldf e funcionou perfeitamente. Demorou 3 horas pra rodar no meu Mac, mas, resolveu o problema e integrou os 2 dataframes perfeitamente!!!
Muito obrigado novamente e um grande abraço!!
Antonio.
1 curtida