【问题标题】:Deleting/ rows if rows do not have atleast 2 recordings for multiple variable如果行没有多个变量的至少 2 个记录,则删除/行
【发布时间】:2021-12-11 00:19:24
【问题描述】:

问题 1) 假设我有 4 名参与者超过 4 年的纵向数据,即 0、1、3、4 年。 我的目标是

  1. 检查数据是否至少记录了任意 2 个时间点的结果变量 (n1)。
  2. 如果只存在一个记录,则删除;否则保留它。
  3. 对多个结果变量 (m1) 重复 1) 和 2)

我拥有的数据

ID  visit   n1  m1
1   0   5.6 0
1   1   1.5 NA
1   3   0.5 NA
1   4   NA  NA
2   0   6   1
2   1   NA  0
2   3   NA  0
2   4   NA  0
3   0   3.4 0
3   1   2.4 0
3   3   2.5 0
3   4   1   1
4   0   NA  NA
4   1   NA  NA
4   3   NA  NA
4   4   3.3 0

这就是我想要的

data 1       
ID  visit   n1
1   0   5.6
1   1   1.5
1   3   0.5
1   4   NA
3   0   3.4
3   1   2.4
3   3   2.5
3   4   1

data2        
ID  visit   m1
2   0   1
2   1   0
2   3   0
2   4   0
3   0   0
3   1   0
3   3   0
3   4   1

或者我们创建新变量 n12 的这种形式(n1 存在 0= =2 存在 n1 值)&类似地 m12。稍后我可以根据这些新变量 n12 和 m12 的值删除行。

ID  visit   n1  m1  n12 m12
1    0   5.6 0  1   0
1    1   1.5 NA 1   0
1    3   0.5 NA 1   0
1    4   NA  NA 1   0
2    0   6   1  0   1
2    1   NA  0  0   1
2    3   NA  0  0   1
2    4   NA  0  0   1
3    0   3.4 0  1   1
3    1   2.4 0  1   1
3    3   2.5 0  1   1
3    4   1   1  1   1
4    0   NA  NA 0   0
4    1   NA  NA 0   0
4    3   NA  NA 0   0
4    4   3.3 0  0   0

我试过Deleting incomplete cases across multiple rows in R studio 但是下面的代码在 mydata 中给了我 '0' 的观察结果,因为即使跨行发现单个 NA 也会删除行

mydata = mydata[!mydata$ID %in% mydata[!complete.cases(mydata) ,]$ID, ]

library(plyr)
# counts all the IDs
cnt = count(mydata, "ID")
# Eliminates any ID that doesn't have 2 observations
mydata[mydata$ID %in% cnt[cnt$freq == 2, ]$ID, ]

我也尝试了长到宽格式,这不起作用,因为我猜我的值是多个变量

library(dplyr)    
mydata <- mydata %>%
tidyr::spread(key=time, value=value) %>% # reformat to wide
na.omit() %>% # delete cases with missingness on any variable (i.e. any time point)
tidyr::gather(key="time", value="value", -ID) # put it back in long format

新问题 2):如果我只想拥有 n1 的访问 =0 值的行以及 n1 的至少一次其他访问 (1/3/4) 记录,我应该如何编码?获取这样的数据:

ID  visit   n1  
1   0   5.6 
1   1   1.5 
1   3   0.5 
1   4   NA  
3   0   3.4 
3   1   2.4 
3   3   2.5 
3   4   1

请建议 R 语法或方法来实现目标 谢谢!

【问题讨论】:

    标签: r longitudinal


    【解决方案1】:
    dat <- structure(list(
      ID = c("1", "1", "1", "1", "2", "2", "2", "2", "3", "3", "3", "3", "4", "4", "4", "4"),
      visit = c("0", "1", "3", "4", "0", "1", "3", "4", "0", "1", "3", "4", "0", "1", "3","4"),
      n1 = c("5.6", "1.5", "0.5", NA, "6", NA, NA, NA, "3.4","2.4", "2.5", "1", NA, NA, NA, "3.3"),
      m1 = c("0", NA, NA, NA, "1", "0", "0", "0", "0", "0", "0", "1", NA, NA, NA, "0")),
      row.names = 2:17, class = "data.frame")
    
    library(dplyr)
    
    dat %>%
      group_by(ID) %>%
      filter(sum(!is.na(n1)) >= 2) %>%
      assign("data1", ., inherits = TRUE)
    data1
    #> # A tibble: 8 x 4
    #> # Groups:   ID [2]
    #>   ID    visit n1    m1   
    #>   <chr> <chr> <chr> <chr>
    #> 1 1     0     5.6   0    
    #> 2 1     1     1.5   <NA> 
    #> 3 1     3     0.5   <NA> 
    #> 4 1     4     <NA>  <NA> 
    #> 5 3     0     3.4   0    
    #> 6 3     1     2.4   0    
    #> 7 3     3     2.5   0    
    #> 8 3     4     1     1
    
    dat %>%
      group_by(ID) %>%
      filter(sum(!is.na(m1)) >= 2) %>%
      assign("data2", ., inherits = TRUE)
    data2
    #> # A tibble: 8 x 4
    #> # Groups:   ID [2]
    #>   ID    visit n1    m1   
    #>   <chr> <chr> <chr> <chr>
    #> 1 2     0     6     1    
    #> 2 2     1     <NA>  0    
    #> 3 2     3     <NA>  0    
    #> 4 2     4     <NA>  0    
    #> 5 3     0     3.4   0    
    #> 6 3     1     2.4   0    
    #> 7 3     3     2.5   0    
    #> 8 3     4     1     1
    
    dat %>%
      group_by(ID) %>%
      mutate(n12 = ifelse(sum(!is.na(n1)) >= 2, 1, 0)) %>%
      mutate(m12 = ifelse(sum(!is.na(m1)) >= 2, 1, 0))
    #> # A tibble: 16 x 6
    #> # Groups:   ID [4]
    #>    ID    visit n1    m1      n12   m12
    #>    <chr> <chr> <chr> <chr> <dbl> <dbl>
    #>  1 1     0     5.6   0         1     0
    #>  2 1     1     1.5   <NA>      1     0
    #>  3 1     3     0.5   <NA>      1     0
    #>  4 1     4     <NA>  <NA>      1     0
    #>  5 2     0     6     1         0     1
    #>  6 2     1     <NA>  0         0     1
    #>  7 2     3     <NA>  0         0     1
    #>  8 2     4     <NA>  0         0     1
    #>  9 3     0     3.4   0         1     1
    #> 10 3     1     2.4   0         1     1
    #> 11 3     3     2.5   0         1     1
    #> 12 3     4     1     1         1     1
    #> 13 4     0     <NA>  <NA>      0     0
    #> 14 4     1     <NA>  <NA>      0     0
    #> 15 4     3     <NA>  <NA>      0     0
    #> 16 4     4     3.3   0         0     0
    Created on 2021-12-16 by the reprex package (v2.0.1)
    

    行为示范:

    # Let's look at one ID
    # group_by() is essentially doing the same thing
    # i.e., summarizing by group
    id1 <- dat[dat$ID==1,]
    id1
    #>   ID visit   n1   m1
    #> 2  1     0  5.6    0
    #> 3  1     1  1.5 <NA>
    #> 4  1     3  0.5 <NA>
    #> 5  1     4 <NA> <NA>
    
    # Test for NA in variable n1
    is.na(id1$n1)
    #> [1] FALSE FALSE FALSE  TRUE
    
    # Identify values that aren't NA
    !is.na(id1$n1)
    #> [1]  TRUE  TRUE  TRUE FALSE
    
    # Count values that aren't NA
    sum(!is.na(id1$n1))
    #> [1] 3
    
    # For the first approach:
    #
    # Filter() keeps values that meet the criteria
    # In this case, we are keeping IDs with more than 2 non-NAs in the focal variable (n1)
    #
    # Create object in the environment based on this dplyr chain
    # named "data2";
    # using data from dplyr chain ".";
    # inherits=TRUE makes it available outside of the chain
    assign(x="data1", value=., inherits=TRUE)
    
    # For the second approach:
    #
    # If the number of non-NAs is greater than 2 (per your criteria),
    # return a 1, otherwise 0, in a new column
    # A result of 1 here indicates this ID has two or more values that are non-NA
    ifelse(test=sum(!is.na(id1$n1)) >= 2, yes=1, no=0)
    #> [1] 1
    
    

    【讨论】:

    • 谢谢!此代码有效。但是,我如何验证它是否符合我的要求?任何交叉验证语法?或者你能解释一下代码行吗(例如代码行“group_by(ID)”=我们要求按 ID 分组,“%>%”=在数据内,“filter(sum(!is.na(n1))>= 2)"= 如果 sum >=2,则在前一个集合中过滤,"!is.na(n1)"=n1 中不是 NA,等等)
    • 不客气!我不确定“交叉验证语法”是什么,但我在我的答案中添加了另一个块,演示了代码的行为和一些注释。如果还有什么不清楚的,请告诉我。
    • 再次感谢!我对所提供的代码行的含义感到困惑。混淆1)在“filter(sum(!is.na(n1))> = 2)%>%”行中:我认为sum函数会将变量n1中的所有非NA值相加。如果该总和大于/等于 2,那么它将过滤这些行。例如当 5.6+1.5+0.5=7.6, sum 7.6>2 则保持 ID1;而当我们说0.1 + 0.2 + 0.5 = 0.8时,总和0.8
    • 有很多嵌套,所以有点混乱。我试图在上面的演示中分解嵌套。 !is.na(n1) 返回一个逻辑向量(“哪些值不是 NA”)。 sum(!is.na(n1)) 返回 TRUE 的计数(“计数非 NA 值”)。然后我们将该计数与您的标准进行比较(即 >2)。这将返回单个 TRUE(“非 NA 值的数量大于 2”)或 FALSE(“非 NA 值的数量小于 2”),用于过滤 df。这一切都发生在每个 ID 中,因为我们指定了 group_by(ID)
    • 我明白了!它是对 n1 中数据的“计数”求和,而不是对 n1 中的“值”求和。这就是我想要的;干得好!假设我们想通过 ID 对变量的值求和,那么可能会有多不同?您还可以解释下一行代码“assign("data2", ., inherits = TRUE"吗?
    猜你喜欢
    • 2020-05-28
    • 1970-01-01
    • 2022-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    • 1970-01-01
    • 2021-05-02
    相关资源
    最近更新 更多