AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78126848
Accepted
arnyeinstein
arnyeinstein
Asked: 2024-03-08 17:56:25 +0800 CST2024-03-08 17:56:25 +0800 CST 2024-03-08 17:56:25 +0800 CST

Compare o número com a string com intervalos e números únicos

  • 772

Eu tenho o seguinte problema

library(tidyverse)
test <- tibble(A = c("1994:2020, 2021"), B = 1995)

Gostaria de verificar se o ano em B está nos anos indicados na coluna A. Os anos na coluna A são uma string (os dados são lidos de um arquivo Excel). O seguinte claramente não funciona (dá "Não", mas eu gostaria de ter "Sim"):

test %>%
  mutate(InA = ifelse(B %in% A, "Yes", "No"))

> test
# A tibble: 1 x 2
  A                   B
  <chr>           <dbl>
1 1994:2020, 2021  1995

Presumo que devo separar a string em A. No entanto, A pode conter mais de um intervalo e/ou mais de um ano (por exemplo, ("1994:2012, 2014, 2016:2020, 2021") e usando "separar" para estruturas diferentes fica complicado.Talvez haja uma maneira mais direta.

  • 5 5 respostas
  • 277 Views

5 respostas

  • Voted
  1. SamR
    2024-03-08T18:19:42+08:002024-03-08T18:19:42+08:00

    Vamos criar mais alguns exemplos:

    test <- data.frame(
        A = c("1994:2020, 2021", "1996", "1994:2012, 2014, 2016:2020, 2021", "1994:2012, 2014, 2016:2020, 2021"),
        B = c(1995, 2022, 2015, 2019),
        expected = c(TRUE, FALSE, FALSE, TRUE)
    )
    #                                  A    B expected
    # 1                  1994:2020, 2021 1995     TRUE
    # 2                             1996 2022    FALSE
    # 3 1994:2012, 2014, 2016:2020, 2021 2015    FALSE
    # 4 1994:2012, 2014, 2016:2020, 2021 2019     TRUE
    

    Se você confiar em sua opinião, poderá avaliá-la.

    Solução Base R

    É assim que eu faria.

    within(test, C  <- Map(
        \(x,y) y %in% eval(str2lang(x)), 
        sprintf("c(%s)", A),
        B,
        USE.NAMES = FALSE
    ))
    #                                  A    B expected     C
    # 1                  1994:2020, 2021 1995     TRUE  TRUE
    # 2                             1996 2022    FALSE FALSE
    # 3 1994:2012, 2014, 2016:2020, 2021 2015    FALSE FALSE
    # 4 1994:2012, 2014, 2016:2020, 2021 2019     TRUE  TRUE
    

    tidyversesolução

    Ao carregar library(tidverse)sua pergunta, você também pode fazer:

    test |> 
        dplyr::mutate(
            C = purrr::map2_lgl(
            A,
            B, 
            \(x,y) y %in% rlang::eval_tidy(
                rlang::parse_expr(
                    glue::glue("c({x})")
                )
            )
        )
    )
    

    Observe que ambas as abordagens também funcionarão se Acontiverem intervalos não contíguos, por exemplo 1994:2012, 2014, o que nem todas as respostas funcionarão.

    Isenção de responsabilidade obrigatória

    Com qualquer abordagem, vale a pena ler Avaliar a expressão dada como uma string e Quais são especificamente os perigos de eval(parse(...))? . Não use esta abordagem se você não controlar os dados de entrada. Imagine um quadro de dados de entrada contendo strings como esta.

    test <- data.frame(A = "warning('You have been hacked!')", B = 1995)
    

    Ambas as abordagens executarão o código e imprimirão o aviso. Portanto, se esta for uma possibilidade, use uma abordagem diferente.

    • 9
  2. ThomasIsCoding
    2024-03-08T18:34:23+08:002024-03-08T18:34:23+08:00

    Ideia

    Se você só precisa saber se um ponto cai em um intervalo , você só precisa saber as relações entre o ponto e ambas as arestas desse intervalo.

    Matematicamente, dado um ponto pe um intervalo [lb, ub], pestá dentro do intervalo (incluindo as arestas) se e somente se (p-lb)*(p-ub) <= 0 , e assim você pode tentar prod(p - c(lb,ub))verificar apenas seu sinal.

    Código

    Você pode tentar o código abaixo (também obrigado pelos dados fornecidos por @Roland )

    transform(
        test,
        inrange = mapply(
            \(x, y) prod(y - range(as.numeric(x))),
            strsplit(A, "\\D+"), B
        ) <= 0
    )
    

    que dá

                    A    B inrange
    1 1994:2020, 2021 1995    TRUE
    2 1994:2020, 2021 2021    TRUE
    3 1994:2020, 2021 2022   FALSE
    
    • 9
  3. Roland
    2024-03-08T18:18:38+08:002024-03-08T18:18:38+08:00

    Isso não será rápido para grandes dados, mas funciona:

    test <- data.frame(A = c("1994:2020, 2021", "1994:2020, 2021", "1994:2020, 2021"), 
                       B = c(1995, 2021, 2022))
    
    test$ranges <- strsplit(test$A, ", ", fixed = TRUE)
    
    foo <- function(x, y) {
      y <- strsplit(y, ":", fixed = TRUE)
      any(
        sapply(y, \(z, x) {
          z <- as.integer(z) 
          if (length(z) == 1L) return(z == x)
          x >= z[1] && x <= z[2] 
      }, x = x)
      )
    }
    
    mapply(foo, x = test$B, y = test$ranges)
    #[1]  TRUE  TRUE FALSE
    

    Primeiro dividimos os caracteres em intervalos individuais e depois dividimos esses intervalos para obter seus limites. Comparar com limites é fácil, assim como comparar com um único ano (em vez de um intervalo).

    • 8
  4. Isaac
    2024-03-08T18:24:26+08:002024-03-08T18:24:26+08:00

    Esta é outra opção de como fazer:

    library(tidyverse)
    
    # Sample data
    test <- tibble(A = c("1994:2020, 2021", "2000:2005, 2008:2010, 2015", "1980, 1985:1990", "1999:2002"), 
                   B = c(1995, 2004, 1986, 3000))
    
    test |> 
      mutate(
        InA = map2_lgl(B, str_split(A, ", "), ~ {
          years <- unlist(str_split(.y, ":|-"))
          any(.x >= as.integer(years[1]) & .x <= as.integer(years[length(years)]))
        })
      ) |> 
      mutate(InA = ifelse(InA, "Yes", "No"))
    
    # A tibble: 4 × 3
      A                              B InA  
      <chr>                      <dbl> <chr>
    1 1994:2020, 2021             1995 Yes  
    2 2000:2005, 2008:2010, 2015  2004 Yes  
    3 1980, 1985:1990             1986 Yes  
    4 1999:2002                   3000 No 
    
    • 3
  5. Best Answer
    AnilGoyal
    2024-03-08T18:48:36+08:002024-03-08T18:48:36+08:00

    Equivalente do Tidyverse à estratégia de @SamR

    library(tidyverse)
    
    test <- tibble(A = c("1994:2020, 2021"), B = 1995)
    
    test %>%
      mutate(InA = map2_lgl(A, B, ~ .y %in% eval(str2lang(
        paste0("c(", .x, ")")
      ))))
    #> # A tibble: 1 × 3
    #>   A                   B InA  
    #>   <chr>           <dbl> <lgl>
    #> 1 1994:2020, 2021  1995 TRUE
    

    Criado em 08/03/2024 com reprex v2.0.2

    • 3

relate perguntas

  • Adicionar número de série para atividade de cópia ao blob

  • A fonte dinâmica do empacotador duplica artefatos

  • Selecione linhas por grupo com 1s consecutivos

  • Lista de chamada de API de gráfico subscritoSkus estados Privilégios insuficientes enquanto os privilégios são concedidos

  • Função para criar DFs separados com base no valor da coluna

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve