Select 行包含所有纵向测量值

Select rows with all longitudinal measurements

我有一个包含 ID、Wave (Wave1-4) 和 Score 的纵向数据集。这是具有相同结构的示例数据。原始数据的长度约为 2000,共有 500 名参与者,以长格式表示。

   ID   Wave Score
 1 1001 1    28
 2 1001 2    27 
 3 1001 3    28
 4 1001 4    26
 5 1002 1    30
 6 1002 3    30
 7 1003 1    30
 8 1003 2    30
 9 1003 3    29
 10 1003 4   28
 11 1004 1   22
 12 1005 1   20
 13 1005 2   18
 14 1006 1   22
 15 1006 2   23
 16 1006 3   25
 17 1006 4   19

我想 select 提供 'Score' 的所有四个测量值的“ID”。换句话说,我想要 select 行参与者 'Score' 可用于所有 4 波。 我一直在尝试 select 具有“ID”的行,这些行在所有“Wave”中都有数据。到目前为止,我的试用一直基于这样的想法:如果参与者拥有所有四项测量值,则 ID 将在数据中出现四次。 这就是为什么我试图计算ID的数量,

table(data$id) == 4

虽然它向我显示了数据中出现的每个 ID 的数量,但我无法 select 相应的行。

all.data <- subset(data, subset=table(data$id) == 4)

因为原始数据的长度不同,所以是长格式。 "Length of logical index must be 1 or 2637, not 828" 我需要一个长格式的数据来做进一步的分析,所以我不想改变它。

而不是喂 table(data$ID),尝试

ID %in% names(table(data$ID)[table(data$ID)==4])

因为 table 给出了每个 ID(命名向量)

的出现次数

你可以试试:

df[as.logical(with(df, ave(Wave, ID, FUN = function(x) length(x) == 4))), ]

     ID Wave Score
1  1001    1    28
2  1001    2    27
3  1001    3    28
4  1001    4    26
7  1003    1    30
8  1003    2    30
9  1003    3    29
10 1003    4    28
14 1006    1    22
15 1006    2    23
16 1006    3    25
17 1006    4    19

或者如果你想保持你的基本想法,稍微修改@jay.sf代码:

df[df$ID %in% names(which(table(df$ID) == 4)), ]

我喜欢您的 table() 方法。

> table(d$ID) == 4

 1001  1002  1003  1004  1005  1006 
 TRUE FALSE  TRUE FALSE FALSE  TRUE 

有趣的 ID 在 names() 中。因此,为了让您的代码正常工作,您可以像这样提取 ID

subs <- names(which(table(d$ID) == 4))

并使用 %in% 获得所需的子集。

all.data <- subset(d, subset=d$ID %in% subs)

结果

> all.data
     ID Wave Score
1  1001    1    28
2  1001    2    27
3  1001    3    28
4  1001    4    26
7  1003    1    30
8  1003    2    30
9  1003    3    29
10 1003    4    28
14 1006    1    22
15 1006    2    23
16 1006    3    25
17 1006    4    19

(BTW: 始终确保 ?<name> 没有将任何现有函数名称定义为对象名称,这将为您省去很多麻烦。在您的案例在加载对象之前在新会话中键入 ?data。)

数据

> dput(d)
structure(list(ID = c(1001L, 1001L, 1001L, 1001L, 1002L, 1002L, 
1003L, 1003L, 1003L, 1003L, 1004L, 1005L, 1005L, 1006L, 1006L, 
1006L, 1006L), Wave = c(1L, 2L, 3L, 4L, 1L, 3L, 1L, 2L, 3L, 4L, 
1L, 1L, 2L, 1L, 2L, 3L, 4L), Score = c(28L, 27L, 28L, 26L, 30L, 
30L, 30L, 30L, 29L, 28L, 22L, 20L, 18L, 22L, 23L, 25L, 19L)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", 
"14", "15", "16", "17"))

这是一个快速的data.table回答。

  library(data.table)
  dt <- structure(list(ID = c(1001, 1001, 1001, 1001, 1002, 1002, 1003, 
  1003, 1003, 1003, 1004, 1005, 1005, 1006, 1006, 1006, 1006), 
Wave = c(1, 2, 3, 4, 1, 3, 1, 2, 3, 4, 1, 1, 2, 1, 2, 3, 
4), Score = c(28, 27, 28, 26, 30, 30, 30, 30, 29, 28, 22, 
20, 18, 22, 23, 25, 19)), row.names = c(NA, -17L), class = c("data.table", 
"data.frame"))

dt[ , .(Score, N = uniqueN(.SD)) , by = list(ID), .SDcols = c("Wave")][N == 4,]

 >   ID Score N
 1: 1001    28 4
 2: 1001    27 4
 3: 1001    28 4
 4: 1001    26 4
 5: 1003    30 4
 6: 1003    30 4
 7: 1003    29 4
 8: 1003    28 4
 9: 1006    22 4
10: 1006    23 4
11: 1006    25 4
12: 1006    19 4

为了完整起见,这里有两个data.table解决方案。两者都确定 Wave 的值是 1 到 4 的那些 ID。一种方法使用子集,另一种方法是连接。

子集化

library(data.table)
setDT(df)[ID %in% dt[ , which(uniqueN(Wave) == 4L), by = ID]$ID]
      ID Wave Score
 1: 1001    1    28
 2: 1001    2    27
 3: 1001    3    28
 4: 1001    4    26
 5: 1003    1    30
 6: 1003    2    30
 7: 1003    3    29
 8: 1003    4    28
 9: 1006    1    22
10: 1006    2    23
11: 1006    3    25
12: 1006    4    19

加入

library(data.table)
setDT(df)[df[, .N, .(ID, Wave)][, .N, ID][N == 4L, .(ID)], on = "ID"]

其中returns相同的结果。

数据

library(data.table)
fread("
rn ID   Wave Score
 1 1001 1    28
 2 1001 2    27 
 3 1001 3    28
 4 1001 4    26
 5 1002 1    30
 6 1002 3    30
 7 1003 1    30
 8 1003 2    30
 9 1003 3    29
 10 1003 4   28
 11 1004 1   22
 12 1005 1   20
 13 1005 2   18
 14 1006 1   22
 15 1006 2   23
 16 1006 3   25
 17 1006 4   19", drop = 1L)