【问题标题】:Vlookup() equivalent in DplyrDplyr 中的 Vlookup() 等效项
【发布时间】:2020-05-29 13:50:14
【问题描述】:

我的 df 看起来像:

library(tidyverse) 
df_1 <- tibble::tribble(
          ~sub_date, ~value_1, ~value_2,
          "2020-05",       58,      130,
          "2020-05",       58,       "check",
          "2020-03",       50,      120,
          "2020-03",       55,       "check",
          "2020-03",       55,       "check"
          )

我想用此处的参考值更改包含“check”的行的值:

df_ref <- tibble::tribble(
            ~sub_date, ~ref_value,
            "2020-05",        123,
            "2020-03",        234
            )

基本上 - 仅使用 df_ref 表作为包含检查的行的参考。

我想在 excel 中使用等价的 lookup(),在 if() 函数中使用。

最终结果是:

df_final <- tibble::tribble(
              ~sub_date, ~value_1, ~value_2,
              "2020-05",       58,      130,
              "2020-05",       58,      123,
              "2020-03",       50,      120,
              "2020-03",       55,      234,
              "2020-03",       55,      234
              )

【问题讨论】:

  • 您似乎正在尝试加入。 dplyr.tidyverse.org/reference/join.html
  • 我知道它是连接,但仅适用于行的子集,而不是整个数据框 @cory。当它应用于具有特定字符串的行时,我不明白该怎么做
  • 是的,vlookup 实际上是一个非常糟糕的连接实现,如果你想看到完全错误的结果,你需要以某种方式过滤掉最重要的结果
  • 好的,你明白了。将它分成两部分...加入以创建一个新列,然后将它的 ifelse 子放入您的列中。

标签: r join dplyr tidyverse


【解决方案1】:

这段代码应该可以工作

df_1 %>% 
  mutate(value_2 = as.numeric(na_if(value_2, "check"))) %>% 
  left_join(df_ref, by = "sub_date") %>% 
  mutate(value_2 = coalesce(value_2, ref_value)) %>% 
  select(-ref_value)

小解释:首先我们将"check"的所有值都设置为NA,感谢na_if,然后我们加入查找表,然后我们coalescevalue_2ref_value这两列,即取两者之间的第一个非缺失值。


输出

# A tibble: 5 x 3
#   sub_date value_1 value_2
#   <chr>      <dbl>   <dbl>
# 1 2020-05       58     130
# 2 2020-05       58     123
# 3 2020-03       50     120
# 4 2020-03       55     234
# 5 2020-03       55     234

小提示:您的df_1 不起作用,因为您将其粘贴到您的问题中。下面我将其值调整为字符以便它工作

df_1 <- tibble::tribble(
  ~sub_date, ~value_1, ~value_2,
  "2020-05",       58,      "130",
  "2020-05",       58,      "check",
  "2020-03",       50,      "120",
  "2020-03",       55,      "check",
  "2020-03",       55,      "check"
)

【讨论】:

    【解决方案2】:

    如果有多个匹配项,祝你好运

    library(tidyverse)
    df_1 <- tibble::tribble(
      ~sub_date, ~value_1, ~value_2,
      "2020-05",       58,      "130",
      "2020-05",       58,       "check",
      "2020-03",       50,      "120",
      "2020-03",       55,       "check",
      "2020-03",       55,       "check"
    )
    
    df_ref <- tibble::tribble(
      ~sub_date, ~ref_value,
      "2020-05",        123,
      "2020-03",        234
    )
    
    df_1 %>% 
      left_join(df_ref) %>%
      mutate(value_2_true = ifelse(value_2 == "check",ref_value,value_2)) %>%
      mutate(value_2 = value_2_true %>% as.numeric()) %>% 
      select(-value_2_true,-ref_value)
    

    【讨论】:

      【解决方案3】:

      使用基础 R:

      ref_lut <- with(df_ref, setNames(ref_value, sub_date))
      
      df_1$value_2 <- 
        ifelse(df_1$value_2 == "check", ref_lut[df_1$sub_date], df_1$value_2)
      
      df_1
      
        sub_date value_1 value_2
        <chr>      <dbl> <chr>  
      1 2020-05       58 130    
      2 2020-05       58 123    
      3 2020-03       50 120    
      4 2020-03       55 234    
      5 2020-03       55 234    
      

      【讨论】:

        【解决方案4】:

        您也可以只使用ifelsematch 进行单行操作,因为我们对加入数据框并不真正感兴趣。如果您想要数字输出,请将其包裹在 as.numeric 中。

        library(dplyr)
        
        mutate(df_1, 
               value_2 = ifelse(value_2 == "check", 
                                df_ref$ref_value[match(sub_date, df_ref$sub_date)],
                                value_2))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-29
          • 1970-01-01
          • 2017-11-14
          • 2016-09-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多