【问题标题】:How can I find the column index of the first non-zero value in a row with R dplyr?如何使用 R dplyr 找到行中第一个非零值的列索引?
【发布时间】:2026-01-11 01:35:01
【问题描述】:

我在 R 工作。我有一个 COVID 病例总数数据集,如下所示:

Facility Day_1 Day_2 Day_3
A 0 0 1
B 1 2 5
C 0 2 6
D 0 0 0

我想使用 mutate() 创建一个新列 first_case,它具有每行中第一个非零元素的列索引 - 如果没有非零元素,则为“NA”。我考虑过使用 where(),但不太清楚如何获取列索引而不是行索引。

非常感谢任何帮助!

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    我们可以使用max.col 来获取每个零值都非零时的第一个实例。

    library(dplyr)
    
    df %>%
      mutate(first_case = {
        tmp <- select(., starts_with('Day'))
        ifelse(rowSums(tmp) == 0, NA, max.col(tmp != 0, ties.method = 'first'))
      })
    
    #  Facility Day_1 Day_2 Day_3 first_case
    #1        A     0     0     1          3
    #2        B     1     2     5          1
    #3        C     0     2     6          2
    #4        D     0     0     0         NA
    

    first_case'Day' 列的列号,如果您需要数据中的列号,您可以在上面的输出中添加+ 1

    【讨论】:

    • 这很好用而且很容易理解!谢谢,已采纳
    【解决方案2】:

    这可能是不必要的复杂,因为数据不是 dplyr 等期望的长(“整齐”)格式。

    datlong <- dat %>%
      pivot_longer(cols=starts_with("Day"), names_to = c("day"), names_pattern="_(\\d+)")
    
    ## A tibble: 12 x 3
    #   Facility day   value
    #   <chr>    <chr> <int>
    # 1 A        1         0
    # 2 A        2         0
    # 3 A        3         1
    # 4 B        1         1
    # 5 B        2         2
    # 6 B        3         5
    # 7 C        1         0
    # 8 C        2         2
    # 9 C        3         6
    #10 D        1         0
    #11 D        2         0
    #12 D        3         0
    

    然后很容易让第一天/第二天/第三天/[n]天高于任何值,以及计算最小值、最大值、平均值、周平均值、滚动平均值等等,因为您现在正在处理普通的旧值向量,而不是跨多列的值列表。

    datlong %>%
      group_by(Facility) %>%
      filter(value > 0, .preserve=TRUE) %>%
      summarise(first_day = first(day))
    
    #`summarise()` ungrouping output (override with `.groups` argument)
    ## A tibble: 4 x 2
    #  Facility first_day
    #  <chr>    <chr>    
    #1 A        3        
    #2 B        1        
    #3 C        2        
    #4 D        <NA>    
    

    使用索引和其他东西的替代方法,不像 dplyr-like:

    datlong %>%
      group_by(Facility) %>%
      summarise(first_day = day[value > 0][1])
    

    【讨论】:

      最近更新 更多