A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/ipeaGIT/geocodebr/issues/37 below:

Solucao de empates mais refinada · Issue #37 · ipeaGIT/geocodebr · GitHub

Contexto

A versão v0.1.0 do {geocodebr} faz um tratamento muito simplicado para solucionar empates. O que o pacote faz atualmente:

Problema

O {geocodebr} atualmente tem uma posicao mais conservadora de apontar como empate qualquer caso suspeito. Por exemplo, quando "tipo_resultado" é igual "dl03", a gente encontra só logradouro e bairro. MAS {geocodebr} aponta empate quando o resultado traz pontos com o mesmo logradouro e bairro com ceps diferentes. A questão é que é normal uma rua ter diferentes CEPS. Exemplo nesse caso aqui de uma rua com dois ceps

Entao o comportamento atual inflaciona muito o número de empates e faz uma correção 'grosseira' nivelando por baixo.

Solução

Reescrevi a função de trata_empates_geocode() abaixo que busca lidar com 3 casos distintos:

a. Resultados não empatados
b. Casos de empate perdidos, i.e. que nao tem muito bem como recuperar.

c) Casos de empate que dá pra salvar

A função abaixo resolves os casos tipo (c) apenas se o usurio passar o parametro resolver_empates = TRUE. No entanto, uma alternativa seria nós resolvermos logo de cara os casos (c) e bem contabilizar como empate, que é o que ja fazemos com pontos localizamos a menos de 200 metros de distancia.

trata_empates_geocode <- function(output_df = parent.frame()$output_df,
                                  resolver_empates = parent.frame()$resolver_empates,
                                  verboso = parent.frame()$verboso) {

  # encontra casos de empate
  output_df[, empate := ifelse(.N > 1, TRUE, FALSE), by = tempidgeocodebr]

  # calcula distancias entre casos empatados
  output_df[empate == TRUE,
            dist_geocodebr := dt_haversine(
              lat, lon,
              data.table::shift(lat), data.table::shift(lon)
            ),
            by = tempidgeocodebr
            ]

  # coloca distancia 0 p/ primeiro caso
  output_df[empate == TRUE,
            dist_geocodebr := ifelse(is.na(dist_geocodebr), 0, dist_geocodebr)
            ]

  # ignora casos com dist menor do q 300 metros
  output_df2 <- output_df[ empate==FALSE |
                           empate==TRUE & dist_geocodebr == 0 |
                           dist_geocodebr > 300
                           ]

  # update casos de empate
  output_df2[, empate := ifelse(.N > 1, TRUE, FALSE), by = tempidgeocodebr]

  # conta numero de casos empatados
  ids_empate <- output_df2[empate == TRUE, ]$tempidgeocodebr
  n_casos_empate <- unique(ids_empate) |> length()


  # se nao for para resolver empates:
  # - gera warning
  # - retorna resultado assim mesmo
  if (isFALSE(resolver_empates)) {

    cli::cli_warn(
      "Foram encontrados {n_casos_empate} casos de empate. Estes casos foram marcados com valor igual `TRUE` na coluna 'empate',
       e podem ser inspecionados na coluna 'endereco_encontrado'. Alternativamente, use `resolver_empates==TRUE` para que o pacote
       lide com os empates automaticamente."
    )
  }



  # se for para resolver empates, trata de 3 casos separados
  # a) nao empatados
  # b) empatados perdidos (dis > 1Km e lograoduros ambiguos)
  #    solucao: usa caso com maior contagem_cnefe
  # c) empatados mas que da pra salvar (dist < 1km e logradouros nao ambiguos)
  #    solucao: agrega casos provaveis de serem na mesma rua com media ponderada
  #    das coordenadas, mas retorna  endereco_encontrado do caso com maior
  #    contagem_cnefe

  if (isTRUE(resolver_empates)) {

    # a) casos sem empate
    df_sem_empate <- output_df2[empate == FALSE]
    ids_sem_empate <- df_sem_empate$tempidgeocodebr


    # b) empatados perdidos (dis > 1Km e lograoduros ambiguos)  ---------------------------

    # identifica lograoduros ambiguos (e.g. RUA A)
    num_ext <- c(
      'UM',
      'DOIS',
      'TRES',
      'QUATRO',
      'CINCO',
      'SEIS',
      'SETE',
      'OITO',
      'NOVE',
      'DEZ',
      'ONZE',
      'DOZE',
      'TREZE',
      'QUATORZE',
      'QUINZE',
      'DEZESSEIS',
      'DEZESSETE',
      'DEZOITO' ,
      'DEZENOVE',
      'VINTE',
      'TRINTA',
      'QUARENTA',
      'CINQUENTA',
      'SESSENTA',
      'SETENTA',
      'OITENTA',
      'NOVENTA'
    )

    ruas_letras <- paste(paste("RUA", LETTERS), collapse = " |")
    ruas_numerais <- paste(paste("RUA", 1:30), collapse = " |")
    ruas_num_ext <- paste(paste("RUA", num_ext), collapse = " |")

    ruas_letras <- paste0(ruas_letras, " ")
    ruas_numerais <- paste0(ruas_numerais, " ")
    ruas_num_ext <- paste0(ruas_num_ext, " ")

    # casos empatados muito distantes
    ids_empate_too_distant <- output_df2[empate == TRUE & dist_geocodebr>1000]$tempidgeocodebr

    empates_perdidos <- output_df2[
      empate == TRUE &
        (
          tempidgeocodebr %in% ids_empate_too_distant |
            endereco_encontrado %like% ruas_letras      |
            endereco_encontrado %like% ruas_numerais    |
            endereco_encontrado %like% ruas_num_ext     |
            endereco_encontrado %like% 'ESTRADA|RODOVIA'
        )
    ]

    # ainda dah pra salvar enderecos com datas (e.g. 'RUA 15 DE NOVEMBRO')
    meses_pattern <- "\\b\\DE (JANEIRO|FEVEREIRO|MARÇO|ABRIL|MAIO|JUNHO|JULHO|AGOSTO|SETEMBRO|OUTUBRO|NOVEMBRO|DEZEMBRO)\\b"
    empates_perdidos <- empates_perdidos[ ! grepl(meses_pattern, logradouro_encontrado) ]

    # selecting the row with max 'contagem_cnefe'
    empates_perdidos <- empates_perdidos[empates_perdidos[, .I[contagem_cnefe == max(contagem_cnefe)], by = tempidgeocodebr]$V1]
    empates_perdidos <- empates_perdidos[empates_perdidos[, .I[1], by = tempidgeocodebr]$V1]


    # c) casos de empate que podem ser salvos ---------------------------------
    ids_empate_salve <- output_df2[!tempidgeocodebr %in% c(ids_sem_empate, empates_perdidos$tempidgeocodebr)]$tempidgeocodebr
    empates_salve <- output_df2[ tempidgeocodebr %in% ids_empate_salve ]

    # check if we left anyone behind
    length(unique(output_df2$tempidgeocodebr)) == sum(
      length(ids_sem_empate),
      length(unique(empates_perdidos$tempidgeocodebr)) ,
      length(unique(ids_empate_salve))
    )

    # calcula media ponderada das coordenadas
    # fica com caso que tem max 'contagem_cnefe'
    empates_salve[, c('lat', 'lon') := list(weighted.mean(lat, w = contagem_cnefe),
                                            weighted.mean(lon, w = contagem_cnefe)
    ),
    by = tempidgeocodebr]

    # selecting the row with max 'contagem_cnefe'
    empates_salve <- empates_salve[empates_salve[, .I[contagem_cnefe == max(contagem_cnefe)], by = tempidgeocodebr]$V1]
    empates_salve <- empates_salve[empates_salve[, .I[1], by = tempidgeocodebr]$V1]


    # junta tudo
    output_df2 <- data.table::rbindlist(list(df_sem_empate, empates_salve, empates_perdidos))
    output_df2[, 'contagem_cnefe' := NULL]

    if (verboso) {
      plural <- ifelse(n_casos_empate==1, 'caso', 'casos')
      message(glue::glue(
        "Foram encontrados e resolvidos {n_casos_empate} {plural} de empate."
      ))
    }
  }

  # drop geocodebr dist columns
  output_df2[, dist_geocodebr := NULL]

  return(output_df2)
}

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4