2017-04-04 29 views
4

我有一个数据文件,每个参与者一行(根据他们参与的研究命名为1-x)。我想检查是否所有参与者都存在于数据集中。这是我的玩具的数据集,PERSONID是参与者,研究他们在参加研究检查计数器变量中的步骤是否丢失

df <- read.table(text = "personid study measurement 
1   x  23 
2   x  32 
1   y  21 
3   y  23 
4   y  23 
6   y  23", header=TRUE) 

看起来像这样:

personid study measurement 
1  1 x   23 
2  2 x   32 
3  1 y   21 
4  3 y   23 
5  4 y   23 
6  6 y   23 

所以对于Y,我很想念参与者2和5 。我如何自动检查?我尝试添加一个计数器变量并将该计数器变量与参与者ID进行比较,但是一旦缺少一个参与者,比较就没有意义,因为对齐关闭。

df %>% group_by(study) %>% mutate(id = 1:n(),check = id==personid) 
Source: local data frame [6 x 5] 
Groups: date [2] 

    personid study measurement id check 
    <int> <fctr>  <int> <int> <lgl> 
1  1  x   23  1 TRUE 
2  2  x   32  2 TRUE 
3  1  y   21  1 TRUE 
4  3  y   23  2 FALSE 
5  4  y   23  3 FALSE 
6  6  y   23  4 FALSE 
+0

什么是你想在这里所需的输出?你只是试图添加这个“检查”列,以便数据库中的每一行都是真的,如果该参与者在每个研究中? – MrFlick

+0

也许“检查”列的想法不理想,我期望的输出是沿着“y缺少参与者2和5”的线,不关心格式。 – Esther

回答

4

假设你personid是连续的,那么你可以使用setdiff,即

library(dplyr) 

df %>% 
group_by(study) %>% 
mutate(new = toString(setdiff(max(personid):min(personid), personid))) 

#Source: local data frame [6 x 4] 
#Groups: study [2] 

# personid study measurement new 
#  <int> <fctr>  <int> <chr> 
#1  1  x   23  
#2  2  x   32  
#3  1  y   21 5, 2 
#4  3  y   23 5, 2 
#5  4  y   23 5, 2 
#6  6  y   23 5, 2 
3

一种方法是使用tidy::expand()产生的studypersonid所有可能的组合,然后使用anti_join()删除做到这一点实际出现在数据中的组合。

library(dplyr, warn.conflicts = FALSE) 
library(tidyr) 

df %>% 
    expand(study, personid) %>% 
    anti_join(df) 
#> Joining, by = c("study", "personid") 
#> # A tibble: 4 × 2 
#> study personid 
#> <fctr> <int> 
#> 1  y  2 
#> 2  x  6 
#> 3  x  4 
#> 4  x  3 
+0

这是个好主意,这实际上是最有用的输出。虽然这个例子并没有给出正确的输出结果,但我想告诉脚本,对于x,我希望所有数字都达到2(1:2),对于y所有数字达到6(1:6) – Esther

+0

In在这种情况下,使用expand()生成全部可能的值 – hadley

+0

这是有道理的,但我无法围绕如何使用不同的最大值来扩展我的头。我只是做'展开(c(“x”,“y”),1:6)',然后排除我不需要的行(即y 3-6)?似乎可能有更合乎逻辑的方法来做到这一点? – Esther

2

使用基础R

tapply(df$personid, df$study, function(a) setdiff(min(a):max(a), a)) 

输出一个简单的解决方案:

$x 
integer(0) 

$y 
[1] 2 5