【问题标题】:Subsetting under multiple conditions多个条件下的子集化
【发布时间】:2022-01-18 17:17:40
【问题描述】:

我想返回在Season Winter1 和 Winter2 中看到的Transmitter 代码的数量。答案应该是 6(在 Winter1 和 Winter2 中看到了 6 个不同的代码)。但是下面的命令返回 0:

length(unique(Dispersion[(Dispersion$Season == "Winter1") & (Dispersion$Season == "Winter2"),]$Transmitter))

什么命令适合我的问题?

structure(list(Transmitter = c("A69-1602-59814", "A69-1602-59814", 
"A69-1602-59815", "A69-1602-59815", "A69-1602-59819", "A69-1602-59820", 
"A69-1602-59821", "A69-1602-59822", "A69-1602-59823", "A69-1602-59824", 
"A69-1602-59825", "A69-1602-59826", "A69-1602-59826", "A69-1602-59827", 
"A69-1602-59828", "A69-1602-59828", "A69-1602-59830", "A69-1602-59831", 
"A69-1602-59831", "A69-1602-59832", "A69-1602-59833", "A69-1602-59834", 
"A69-1602-59835", "A69-1602-59835", "A69-1602-59836"), Batch.location = c("Lemmer", 
"Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", 
"Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", 
"Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", 
"Lemmer", "Lemmer", "Lemmer"), Location.Dispersion = c("Lemmer", 
"Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", 
"Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", 
"Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", 
"Lemmer", "Lemmer", "Lemmer"), Season = c("Winter1", "Winter2", 
"Winter1", "Winter2", "Winter1", "Winter1", "Winter1", "Winter1", 
"Winter1", "Winter1", "Winter1", "Winter1", "Winter2", "Winter1", 
"Winter1", "Winter2", "Winter1", "Winter1", "Winter2", "Winter1", 
"Winter1", "Winter1", "Winter1", "Winter2", "Winter1"), Freq = c(1961L, 
2075L, 310L, 1L, 2880L, 305L, 366L, 834L, 19L, 2580L, 564L, 997L, 
3475L, 6447L, 988L, 2991L, 355L, 3147L, 6155L, 903L, 484L, 321L, 
76L, 1921L, 3329L)), row.names = c(NA, -25L), groups = structure(list(
    Transmitter = c("A69-1602-59814", "A69-1602-59815", "A69-1602-59819", 
    "A69-1602-59820", "A69-1602-59821", "A69-1602-59822", "A69-1602-59823", 
    "A69-1602-59824", "A69-1602-59825", "A69-1602-59826", "A69-1602-59827", 
    "A69-1602-59828", "A69-1602-59830", "A69-1602-59831", "A69-1602-59832", 
    "A69-1602-59833", "A69-1602-59834", "A69-1602-59835", "A69-1602-59836"
    ), Batch.location = c("Lemmer", "Lemmer", "Lemmer", "Lemmer", 
    "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", 
    "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", 
    "Lemmer", "Lemmer", "Lemmer"), Location.Dispersion = c("Lemmer", 
    "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", 
    "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", 
    "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer", "Lemmer"
    ), .rows = structure(list(1:2, 3:4, 5L, 6L, 7L, 8L, 9L, 10L, 
        11L, 12:13, 14L, 15:16, 17L, 18:19, 20L, 21L, 22L, 23:24, 
        25L), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), row.names = c(NA, -19L), class = c("tbl_df", 
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"))

【问题讨论】:

    标签: r conditional-statements subset


    【解决方案1】:

    您需要按Transmitter 分组(您的尝试中缺少)并确保两个值都在Season 的每组中。

    dplyr

    library(dplyr)
    out <- dat %>%
      group_by(Transmitter) %>%
      filter(all(c("Winter1", "Winter2") %in% Season)) %>%
      ungroup()
    out
    # # A tibble: 12 x 5
    #    Transmitter    Batch.location Location.Dispersion Season   Freq
    #    <chr>          <chr>          <chr>               <chr>   <int>
    #  1 A69-1602-59814 Lemmer         Lemmer              Winter1  1961
    #  2 A69-1602-59814 Lemmer         Lemmer              Winter2  2075
    #  3 A69-1602-59815 Lemmer         Lemmer              Winter1   310
    #  4 A69-1602-59815 Lemmer         Lemmer              Winter2     1
    #  5 A69-1602-59826 Lemmer         Lemmer              Winter1   997
    #  6 A69-1602-59826 Lemmer         Lemmer              Winter2  3475
    #  7 A69-1602-59828 Lemmer         Lemmer              Winter1   988
    #  8 A69-1602-59828 Lemmer         Lemmer              Winter2  2991
    #  9 A69-1602-59831 Lemmer         Lemmer              Winter1  3147
    # 10 A69-1602-59831 Lemmer         Lemmer              Winter2  6155
    # 11 A69-1602-59835 Lemmer         Lemmer              Winter1    76
    # 12 A69-1602-59835 Lemmer         Lemmer              Winter2  1921
    

    从这里您可以使用n_distinct 或其他东西来计算您需要的唯一Transmitter 值。

    summarize(out, n = n_distinct(Transmitter))
    # # A tibble: 1 x 1
    #       n
    #   <int>
    # 1     6
    

    或者只是

    length(unique(out$Transmitter))
    # [1] 6
    

    基础 R,选项 1

    ind <- ave(dat$Season, dat$Transmitter,
               FUN = function(z) all(c("Winter1", "Winter2") %in% z)) == "TRUE"
    ind
    #  [1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE
    # [21] FALSE FALSE  TRUE  TRUE FALSE
    dat[ind,]
    # ...
    
    length(unique(dat[ind, "Transmitter"]))
    # [1] 6
    

    == "TRUE" 使用字符 "TRUE" 是因为ave 强制返回值与其第一个参数相同,即dat$Season。它在内部计算logical,但之后被强制转换为字符串。 (只需运行 ave(..) 而不使用 ==... 即可查看此操作。)

    基础 R,选项 2

    sum(aggregate(Season ~ Transmitter, data = dat,
                  FUN = function(z) all(c("Winter1", "Winter2") %in% z))$Season)
    # [1] 6
    

    【讨论】:

    • 我相信 OP 想要 6 作为预期结果。
    • 是的,这就是我建议n_distinct 的原因。我在这里推断,很多问题经常要求计数然后问“哪些?”,所以我想我会通过它。
    【解决方案2】:

    split 按季节,然后使用intersectlength

    with(dat, 
         do.call(\(...) intersect(...), unname(as.list(split(Transmitter, Season))))
         ) |> length()
    # [1] 6
    

    或者使用table 并计算rowSums 等于2 的行数。

    with(dat, table(Transmitter, Season)) |>
      (\(x) x[rowSums(x) == length(unique(dat$Season)), ])() |>
      nrow()
    # [1] 6
    

    【讨论】:

    • 虽然样本数据没有显示出太大的可变性,但我认为 Season 只有两个可能值的假设有点可信。
    • @r2evans 这很重要。我的解决方案 2 现在可能会处理。
    【解决方案3】:

    (Dispersion$Season == "Winter1") &amp; (Dispersion$Season == "Winter2") 正在寻找 Season"Winter1""Winter2" 在同一行(同时)的行,这就是为什么这不起作用。既然您使用的是dplyr,我会这样做:

    Dispersion %>%
      group_by(Transmitter) %>%
      filter(all(c("Winter1", "Winter2") %in% Season)) %>%
      ungroup() %>%
      summarize(n_trans = n_distinct(Transmitter))
    # # A tibble: 1 × 1
    #   n_trans
    #     <int>
    # 1       6
    

    【讨论】:

      【解决方案4】:

      另一个base解决方案:

      sum(by(dat$Season, dat$Transmitter, FUN = \(x) { all(unique(dat$Season) %in% x) }))
      
      # [1] 6
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-02-16
        • 1970-01-01
        • 2011-03-04
        • 1970-01-01
        • 1970-01-01
        • 2019-05-19
        • 1970-01-01
        相关资源
        最近更新 更多