【问题标题】:How to check whether all elements of a nested list are a subset of another list in R如何检查嵌套列表的所有元素是否是R中另一个列表的子集
【发布时间】:2019-12-19 06:19:53
【问题描述】:

为此,我尝试了多种不同的方法,包括this stack,但没有任何方法能正常工作。

我的数据框“SiteVisits”(一个小的子集 dput 在底部)由列 Date(class= 日期)、TagID(class= 数字)、SiteVisits(字符列表)组成,和NumSites(class= 数字)。每行列出了在每个日期中找到单个有机体 (TagID) 的所有站点。

我想根据标签访问的网站来指定标签是在“内部”、“外部”还是“中转”一整天。如果它从不访问外部站点,它只能是“内部”,如果它从不访问内部站点,它只能是“外部”

首先, 我想确定某个日期的 TagID 的所有网站是否都包含在此列表中:

inside <- list(c("Release","IC1", "IC2", "IC3","RGD1"))

如果为真SiteVisit$Location = "INSIDE" ELSE 测试某个日期的 TagID 的所有网站是否都包含在此列表中:

outside <- list(c("ORS1","WC1","WC2","WC3","RGU1","ORN1","ORN2","ORS3","GL1","CVP1","CLRS"))

如果为真SiteVisit$Location = "OUTSIDE" 否则SiteVisit$Location = "TRANSITING"

我尝试了许多不同的dplyrbase 版本来实现这一点,但似乎没有一个能做到这一点。我认为这是因为我没有正确检查 SiteVisit$SiteVisits 的每个元素

我目前的尝试是:

SiteVisit <- SiteVisit %>%
  mutate(Location = ifelse(all(SiteVisits[[]] %in% inside), "INSIDE",
                           ifelse(all(SiteVisits[[]] %in% outside),"OUTSIDE","TRANSITING")))

产生所有“内部”

SiteVisit <- SiteVisit %>%
  mutate(Location = ifelse(all(SiteVisits[] %in% inside), "INSIDE",
                           ifelse(all(SiteVisits[] %in% outside),"OUTSIDE","TRANSITING")))

产生所有“TRANSITING”

另外,尝试在 for 循环中执行此操作也不太奏效

for (i in 1: nrow(SiteVisit)) {SiteVisit$Inside <- 
all(SiteVisit$SiteVisits[[i]] %in% inside)}

产生所有 FALSE 而

all(SiteVisit$SiteVisits[[2]] %in% inside)

是真的

这是我的数据框“SiteVisit”dput 的一小部分:

structure(list(Date = structure(c(15828, 15828, 15847, 15847, 
15847, 15847, 15847, 15847, 15848, 15848, 15848, 15848, 15848, 
15848, 15848, 15848, 15849, 15849, 15849, 15849, 15849, 15849, 
15849, 15850, 15850, 15850, 15850, 15850, 15850, 15850, 15851, 
15851, 15851, 15851, 15851, 15851, 15851, 15851, 15852, 15852, 
15852, 15852, 15852, 15852, 15852, 15853, 15853, 15853, 15853, 
15853, 15853, 15853, 15853, 15853, 15854, 15854, 15854, 15854, 
15854, 15854, 15854, 15854, 15855, 15855, 15855, 15855, 15855, 
15855, 15855, 15855, 15855, 15855, 15855, 15855, 15855, 15855, 
15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, 15856, 
15856, 15856, 15856, 15856, 15857, 15857, 15857, 15857, 15857, 
15857, 15857, 15857, 15857, 15857, 15857), class = "Date"), TagID = c(5717.06, 
6277.06, 5073.06, 5717.06, 11121.1, 11191.1, 11387.1, 11415.1, 
5717.06, 6277.06, 11121.1, 11191.1, 11219.1, 11289.1, 11387.1, 
11415.1, 5717.06, 11121.1, 11191.1, 11219.1, 11289.1, 11387.1, 
11415.1, 5717.06, 11121.1, 11191.1, 11219.1, 11289.1, 11387.1, 
11415.1, 5717.06, 11121.1, 11191.1, 11219.1, 11289.1, 11317.1, 
11387.1, 11415.1, 5717.06, 6277.06, 11191.1, 11219.1, 11289.1, 
11387.1, 11415.1, 5717.06, 6277.06, 9015.01, 9833.06, 11191.1, 
11219.1, 11289.1, 11387.1, 11415.1, 5717.06, 6277.06, 9015.01, 
11191.1, 11219.1, 11289.1, 11387.1, 11415.1, 5641.22, 5717.06, 
6221.06, 6277.06, 7909.22, 9015.01, 9833.06, 11121.1, 11191.1, 
11219.1, 11289.1, 11317.1, 11387.1, 11415.1, 5717.06, 6277.06, 
6529.06, 8119.01, 8545.06, 9015.01, 9497.06, 9833.06, 11191.1, 
11219.1, 11289.1, 11387.1, 11415.1, 5717.06, 6277.06, 6529.06, 
9015.01, 9497.06, 9833.06, 11191.1, 11219.1, 11289.1, 11387.1, 
11415.1), SiteVisits = list("Release", "Release", c("IC2", "IC1", 
"Release"), "IC3", "WC2", "RGD1", c("WC1", "WC3"), "WC3", "IC3", 
    "IC3", "WC2", "RGD1", "IC2", "IC1", "WC1", "WC3", "IC3", 
    "WC2", "RGD1", c("IC2", "IC1"), "IC1", "WC1", "WC3", "IC3", 
    "WC2", "RGD1", "IC2", "IC1", "WC1", "WC3", "IC3", "WC2", 
    "RGD1", "IC2", "IC1", "WC1", "WC1", "WC3", "IC3", "IC3", 
    "RGD1", "IC2", "IC1", "WC1", "WC3", "IC3", "IC3", c("IC3", 
    "Release"), c("IC3", "IC2", "IC1", "Release"), "RGD1", "IC2", 
    "IC1", "WC1", "WC3", "IC3", "IC3", c("IC3", "IC2"), "RGD1", 
    "IC2", "IC1", "WC1", "WC3", "Release", "IC3", "Release", 
    "IC3", c("RGD1", "Release"), c("IC3", "IC2"), c("IC3", "IC1"
    ), "WC2", "RGD1", "IC2", "IC1", "WC1", "WC1", "WC3", "IC3", 
    "IC3", c("RGD1", "Release"), c("RGD1", "Release"), "Release", 
    c("IC3", "IC2", "IC1"), "Release", c("IC3", "IC2", "IC1", 
    "RGD1"), "RGD1", "IC2", "IC1", "WC1", "WC3", "IC3", "IC3", 
    "RGD1", c("IC3", "IC2", "IC1"), "RGD1", c("IC3", "IC1", "RGD1"
    ), "RGD1", "IC2", c("IC2", "IC1"), "WC1", "WC3"), NumSites = c(1L, 
1L, 3L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 4L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 
3L, 1L, 4L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 1L, 3L, 1L, 1L, 
2L, 1L, 1L)), row.names = c(NA, -100L), groups = structure(list(
    Date = structure(c(15828, 15847, 15848, 15849, 15850, 15851, 
    15852, 15853, 15854, 15855, 15856, 15857), class = "Date"), 
    .rows = list(1:2, 3:8, 9:16, 17:23, 24:30, 31:38, 39:45, 
        46:54, 55:62, 63:76, 77:89, 90:100)), row.names = c(NA, 
-12L), class = c("tbl_df", "tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))

【问题讨论】:

    标签: r if-statement nested-lists


    【解决方案1】:

    以下工作将insideoutside 存储为array 而不是list

    inside <- c("Release", "IC1", "IC2", "IC3", "RGD1")
    outside <- c("ORS1", "WC1", "WC2", "WC3", "RGU1", "ORN1", "ORN2", "ORS3", "GL1", "CVP1", "CLRS")
    
    df1$Location <- lapply(df1$SiteVisits, function(x) ifelse(all(x %in% inside), "INSIDE", ifelse(all(x %in% outside), "OUTSIDE", "TRANSIT")))
    

    【讨论】:

    • 这行得通,你能解释一下为什么行得通吗?我想我不明白为什么我们可以在矢量上使用 lapply (df1$SiteVisits)
    • lapply 将函数应用于列表或向量,但会返回一个列表。但是您尝试的方法不起作用的原因是%in% 没有查看数组,因为它嵌套在列表中。将上述更改为%in% unlist(inside) 应该可以工作。
    【解决方案2】:

    想要一个快 1/100 的答案吗? (不是错字*,这比 manotheshark 的答案差得多,但它适用于您的数据结构)。 *这是一个错字! 1/100 而不是 1/10

    for (i in 1:nrow(SiteVisit)) {
      SiteVisit_test$Location[i] <- if (all(unlist(SiteVisit[i, ]$SiteVisits) %in% unlist(inside))) {
        "INSIDE"
      } else if (all(unlist(SiteVisit[i, ]$SiteVisits) %in% unlist(outside))) {
        "OUTSIDE"
      } else {"TRANSITIONING"}
    }
    

    两种方法的基准:

    microbenchmark(
      for_statement = for (i in 1:nrow(SiteVisit)) {
        SiteVisit_test$Location[i] <- if (all(unlist(SiteVisit[i, ]$SiteVisits) %in% unlist(inside))) {
          "INSIDE"
        } else if (all(unlist(SiteVisit[i, ]$SiteVisits) %in% unlist(outside))) {
          "OUTSIDE"
        } else {"TRANSITIONING"}
      },
      lapply_statemnt = lapply(SiteVisit$SiteVisits, function(x) ifelse(all(x %in% inside2), "INSIDE", ifelse(all(x %in% outside2), "OUTSIDE", "TRANSIT")))
    )
    
    Unit: microseconds
                expr     min      lq      mean  median       uq     max neval
       for_statement 28874.4 30082.0 32411.968 31008.3 33108.90 48878.1   100
     lapply_statemnt   268.4   284.2   346.201   295.5   310.85  4114.9   100
    

    我真的不明白为什么 lapply 方法在这里要快得多...可能是因为我要为循环中的每个 i 取消列出。

    【讨论】:

      猜你喜欢
      • 2019-08-11
      • 1970-01-01
      • 2021-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      相关资源
      最近更新 更多