【问题标题】:nested loop and multiple if statement R嵌套循环和多个 if 语句 R
【发布时间】:2015-02-14 09:03:47
【问题描述】:

我有一个数据集a,如下

       Dictionary      ActMin   ActMax
             3145      5        10
             32441     10       19
             3245      25       32
             416356    37       46
             4H22      82       130
             %ABC      1        27

我有另一个数据集b,如下

             ID        Test         Obs     Year
             1         3145-MN      11      1994  
             2         3145-NY      17      1992
             1         416356-FL    57      1995
             1         32441-MN     13      1995
             2         3145-MN      8       1993
             2         3245-NY      27      1983
             3         3245-FL      45      2003
             2         3145-MN      6       2001
             3         %ABC-NY      33      1996
             4         4H22-TX      97      1984

我想做的是像这样生成output

            Id         Test         Obs     Results   Year   Description 
            1          3145-MN      11      High      1994   Tested 3145 High on 1994, 4163 High on 1995,    
            2          3145-NY      17      High      1992   Tested 3145 High on 1992
            1          416356-FL    57      High      1995
            1          32441-MN     13      Normal    1995
            2          3145-MN      8       Normal    1993
            2          3245-NY      27      Normal    1983
            3          3245-FL      45      High      2003   Tested 3245 High on 2003
            2          3145-MN      6       Normal    2001
            3          %ABC-NY      33      High      1996
            4          4H22-TX      27      Normal    1984

第一个数据集a 是一个字典,其中存储了唯一的测试编号31453244 等以及它们的MinimumMaximum

第二个数据集b 是实际测试结果数据集,存储实际观察到的结果。将b 中特定测试的观察值与数据集a 中的最小值和最大值进行比较。如果b 中的观察值大于a 中的实际最小值和最大值,则结果列应更新为high,否则Normaldescription 列应提供每个 ID 列高的测试摘要(每个 ID 1 个摘要)。

在这个复杂的循环、if 语句和结果聚合方面需要帮助。

【问题讨论】:

    标签: r if-statement for-loop dplyr


    【解决方案1】:

    有点复杂,但结果应该和你问的差不多。我设法在基础 R 中获得了 result 列,但对于 Description 我必须使用 data.table

     b$result<-c("Normal","High")[(b$Obs > a$ActMax[match(substr(b$Test,1,4),as.character(a$Dictionary))])+1]
     require(data.table)
     setDT(b)
     b[,Description:=gsub("(, )+$","",c(paste(ifelse(result=="High",paste("Tested",substring(Test,1,4),result,"on",Year),""),collapse=", "),rep("",.N-1))),by=ID]
    

    【讨论】:

    • 类似于我对bergant 提到的你使用substr(b$Test,1,4) 的测试代码可能并不总是长度4
    【解决方案2】:

    使用 dplyr 可能会发现代码更具可读性:

    library(dplyr)
    df_result <-
      b %>%
      ## EDIT mutate( Dictionary = as.numeric(substring(Test,1,4)) ) %>%  
      mutate( Dictionary = as.numeric( gsub("[A-Z,-]+", "", Test )) ) %>%  
      inner_join(a, by = "Dictionary") %>%
      mutate( Results = ifelse( Obs > pmax(ActMin, ActMax), yes = "High", no = "Normal" )) 
    
    df_description <-
      df_result %>%
      filter( Results == "High") %>%
      group_by(ID) %>%
      summarise( 
        Results = Results[1],
        Dictionary = min(Dictionary),
        Description = paste("Tested", Dictionary, "on", Year,collapse = ","))
    
    df_final <- 
      df_result %>%
      left_join( df_description, by = c("ID","Dictionary", "Results")) %>%
      select(ID, Test, Obs, Results, Year, Description)
    

    【讨论】:

    • 您使用substring(Test,1,4) 来捕获b 中的匹配测试代码,但是测试代码的字符串长度不同,有些可能是3145,有些可能是416356,我没有提到这一点在我之前的问题中,我刚刚更新了我的问题。我应该如何更改这部分代码以适应不同的测试代码 ID 长度?
    • 用 gsub 替换子字符串 - 例如 as.numeric( gsub("[A-Z,-]+", "", Test ))
    • 有一些奇怪的测试代码,比如...4H22, %ABC 我用这个代码sub("-.+","",b$TEST) 替换了as.numeric( gsub("[A-Z,...,现在我收到一个错误.....cannot join on columns ...index out of bounds跨度>
    • 删除 b$ 并检查 TEST 是否应该重命名为 Test in sub("-.+","",b$TEST)
    猜你喜欢
    • 2015-10-01
    • 2018-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-30
    • 1970-01-01
    相关资源
    最近更新 更多