2017-04-04 28 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