【问题标题】:Find the first non-missing value in a set of variables for each unique person and then change all NAs to 0 after that point在一组变量中为每个唯一的人找到第一个非缺失值,然后在该点之后将所有 NA 更改为 0
【发布时间】:2021-11-11 17:02:53
【问题描述】:

我有一个宽数据集,每人 1 行。每个人都有一组 12 个变量,代表一年中每个月的访问。如果一个人一个月没有访问,它目前显示为 NA。如果一个人在一个月内多次访问,则数字是访问次数。例如,一名患者在 2 月份首次就诊,他们进行了 2 次就诊。一月列是 NA,因为他们当时没有被看到,二月列是 2,因为他们在那个月有 2 次访问。该人的其余月份是否有访问将相应填写。

我的目标是找到第一个非缺失值,然后在他们第一次访问后没有访问的任何月份都需要更改为 0。我仍然希望将他们第一次访问前的几个月保持为 NA。我提供了“拥有”和“想要”数据集。

我已经尝试过循环、if 语句和函数,但没有任何成功。有人对这种类型的代码有经验吗?

有:

|ID | Jan | Feb | Mar | Apr | May | June | Jul |
|:--|:---:|:---:|:---:|:---:|:---:|:----:|:---:|
| 1 |  NA |  1  |  1  | 2   | NA  | NA   | NA  |
| 2 |  NA | NA  | NA  | 1   | NA  |  NA  |  NA |
| 3 |  1  | NA  | 1   | 3   | 1   | NA   | NA  |  
| 4 |  NA | NA  | NA  | NA  | NA  | 1    | 1   |

想要:

|ID | Jan | Feb | Mar | Apr | May | June | Jul |
|:--|:---:|:---:|:---:|:---:|:---:|:----:|:---:|
| 1 |  NA |  1  |  1  | 2   |  0  | 0    | 0   |
| 2 |  NA | NA  | NA  | 1   | 0  |  0  |  0 |
| 3 |  1  | 0  | 1   | 3   | 1   | 0   | 0  |  
| 4 |  NA | NA  | NA  | NA  | NA  | 1    | 1   |

【问题讨论】:

    标签: r


    【解决方案1】:

    我们可以使用带有max.col 的矢量化选项来查找每行的第一个非NA 元素的列索引,不包括第一列。然后,通过检查这个replicated 索引是否小于colum 索引和(&)来创建一个逻辑矩阵,如果值是NA,则返回一个逻辑matrix,我们用它来子集数据并将 (<-) 分配给 0

    df1[-1][col(df1[-1]) > max.col(!is.na(df1[-1]), 'first')[
             row(df1[-1])] & is.na(df1[-1])] <- 0
    

    -输出

    > df1
      ID Jan Feb Mar Apr May June Jul
    1  1  NA   1   1   2   0    0   0
    2  2  NA  NA  NA   1   0    0   0
    3  3   1   0   1   3   1    0   0
    4  4  NA  NA  NA  NA  NA    1   1
    

    或使用apply

    df1[] <-  t(apply(df1[-1], 1, FUN = function(x) 
        replace(x, seq_along(x) > which(!is.na(x))[1] & is.na(x), 0)))
    

    数据

    df1 <- structure(list(ID = 1:4, Jan = c(NA, NA, 1L, NA), Feb = c(1L, 
    NA, NA, NA), Mar = c(1L, NA, 1L, NA), Apr = c(2L, 1L, 3L, NA), 
        May = c(NA, NA, 1L, NA), June = c(NA, NA, NA, 1L), Jul = c(NA, 
        NA, NA, 1L)), class = "data.frame", row.names = c(NA, -4L
    ))
    

    【讨论】:

    • 太好了,非常感谢!看起来它奏效了。出于学习目的,我也会尝试应用版本。感谢您的帮助!
    • 有没有一种方法可以轻松地操作此代码以再次为每个人找到第一个非 NA 月份,然后将 2 添加到该值,然后查看该值(月 + 2)是否等于另一列?
    • @Sophia 你能发布一个新问题吗?谢谢
    • 是的,我会这样做的。谢谢!
    • @Sophia 谢谢,在不同的帖子中理解预期输出会更容易
    【解决方案2】:

    使用旋转、分组和填充的tidyverse 解决方案:

    library(tidyverse)
    
    df1 <- df1 %>% 
      pivot_longer(-ID) %>% 
      group_by(ID) %>% 
      mutate(temp = 1 * !cumall(is.na(value))) %>%
      fill(temp) %>% 
      mutate(value = ifelse(temp == 1 & is.na(value), 0, value))  %>% 
      pivot_wider(-temp, names_from = name, values_from = value)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-23
      • 1970-01-01
      • 2017-12-18
      • 1970-01-01
      相关资源
      最近更新 更多