【问题标题】:In R, conditionally look up a variable in another dataframe在 R 中,有条件地在另一个数据框中查找变量
【发布时间】:2021-07-21 02:46:50
【问题描述】:

背景

我在 r 中有两个 df,一个叫做 d,另一个叫做 insuranced 包含唯一的 ID 列表以及两个属性 genderzip(与 this 问题无关)。 insurance 包含一些相同的 ID 数字,但它们不是唯一的。它们代表了人们在特定年份的健康保险计划。 insurance 表中的一些 ID 重复,因为该人在那一年拥有多个保险计划(即他们更换了保险公司)。以下是制作这些表格的一些代码:

d <- data.frame(ID = c("a","b","c","d","e","f"), 
                    gender = c("f","f","m","f","m","m"), 
                    zip = c(48601,60107,29910,54220,28173,44663),stringsAsFactors=FALSE)

看起来像:

ID gender zip
a f 48601
b f 60107
c m 29910
d f 54220
e m 28173
f m 44663
insurance <- data.frame(ID = c("a","a","c","d","f","f"), 
                     ins_type = c("public","private","private","private","private","public"), 
                     insurer = c("medicare","aetna","cigna","uhc","uhc","medicaid"),
                     stringsAsFactors = FALSE)

看起来像:

ID ins_type insurer
a public medicare
a private aetna
c private cigna
d private uhc
f private uhc
f public medicaid

这是我的目标:

我需要d 来反映d$ID 中的任何人是否有任何公共 保险,如果有,是哪家保险公司。具体来说,这意味着“查找”insurance 表并在d 中创建两个新变量:首先,一个 1/0 或是/否变量,用于永远拥有公共保险(将此变量称为 d$public);第二,它是哪家保险公司(打电话给d$insurer)。

棘手的一点是我需要d$ID 保持唯一性,因为它必须是我未在此处概述的项目的另一个方面的主键。所以这个想法是,如果任何ID任何公共保险条目,那么d$public 应该得到“1”或“是”或其他任何内容。

想要的结果

我想要一个如下所示的表格:

ID gender zip public insurer
a f 48601 1 medicare
b f 60107 0 NA
c m 29910 0 NA
d f 54220 0 NA
e m 28173 0 NA
f m 44663 1 medicaid

我的尝试

之前有人问过这个问题的不同版本(例如herehere),但我不太明白。

我尝试过使用连接,如下所示:

d2 <- d %>%
  left_join(insurance, by=c("ID"="ID"))

这让我得到了我想要的列,但它使像 a 这样的 ID 重复,这是我不能拥有的。

感谢您的帮助!

【问题讨论】:

    标签: r dplyr merge lookup


    【解决方案1】:
    
    d %>% 
          left_join(insurance %>% filter(ins_type == "public"), by = "ID") %>%
          mutate(public = ! is.na(ins_type)) %>%
          select(-ins_type)
    

    【讨论】:

      【解决方案2】:

      这是一个使用base R的解决方案。不需要安装任何tidyverse相关的包。

      # Define public column based on insurance$ins_type
      df$public <- ifelse(insurance$ins_type == "public", 1, 0)
      
      # Now we'll define df$insurer as the result of applying a function
      # that receives the ids and df$public as arguments.
      
      # if the public type is not 1, return NA, else return the insurer name
      # in the insurance df where type is 1 and id = id
      
      df$insurer <- mapply(
          function(id, type) {
          if(type != 1)
              return(NA)
          return(insurance$insurer[insurance$id == id & insurance$type == type])
          }
          df$id,
          df$public
      )
      

      【讨论】:

      • 在“public”列的第一个定义中,如果在不同的情况下,我想引用该列中的任何条目——而不仅仅是“public”?
      • 如果您想引用任何特定条目,那么您只需将“public”更改为“whatever you want”。现在,如果你想要任何东西,那么继续设置df$public &lt;- 1,因为你不在乎它是什么条目。如果您想要任何条目,但不想要 NA,那么 df$public &lt;- ifelse(!is.na(insurance$ins_type), 1, 0)。现在对于最后一种可能的情况,您可能有超过 2 种可能性(例如,公共、私人、混合)。
      • 在这种情况下,一个很好的可读方法是定义您对这个混合示例感兴趣的条目,例如:entries &lt;- c("public", "mixed"),然后原始代码将类似于df$public &lt;- ifelse(insurance$ins_type %in% entries, 1, 0)。希望这些想法对您有所帮助!
      • 哦,是的,我的意思是“insurance$ins_type 中的任何条目,甚至是 NA”。所以,就像,df$public 不会再公开了,它只是 df$ins_type。所以我猜应该是df$public &lt;- ifelse(insurance$ins_type, 1, 0)
      • 不,那是错误的。 ifelse 通过将第一个参数测试为逻辑条件(它将是真或假)来工作。所以你写它的方式,它没有意义,因为它不是一个合乎逻辑的条件。同样,如果您不关心它是什么条目,则只需将所有“ins_type”设置为 1。或者如果您想保留分类变量,可以将其设置为一个因素。请阅读 Hadley Wickham 的 Advanced R 介绍部分。它会帮你的!
      猜你喜欢
      • 2015-10-03
      • 1970-01-01
      • 2018-04-04
      • 2022-06-17
      • 2020-04-21
      • 2022-06-27
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      相关资源
      最近更新 更多