根据分类变量查找数据集中的常见日期

Finding the common dates in a data set based on a categorical variable

我有一个看起来像这样的数据集:

id    eye    date       notes
1      L   01-01-2000
1      L   01-06-2000
1      R   01-01-2000
1      R   01-03-2000
1      R   01-06-2000
2      L   01-01-2000
2      L   01-04-2000
2      R   01-04-2000
2      R   01-07-2000
2      R   04-09-2001
3      L   01-01-2000
4      L   01-01-2000
4      L   03-03-2001
4      R   03-03-2001

对于每个 id,我希望能够找到眼睛标记为 L 和 R 的常见日期,然后将其输出为数据框。所以它应该看起来像:

id    eye    date       notes
1      L   01-01-2000
1      L   01-06-2000
1      R   01-01-2000
1      R   01-06-2000
2      L   01-04-2000
2      R   01-04-2000
4      L   03-03-2001
4      R   03-03-2001

我一直在尝试 dplyrplyr 的不同变体(下面的示例),但我似乎无法让它做我想做的事。

data %>% group_by(id) %>% do(Reduce(intersect, list(.$date[.$eye == "L"], .$date[.$eye == "R"])))

ddply(data, .(id), summarize, Reduce(intersect, list(.$date[.$eye == "L"], .$date[.$eye == "R"])))

从语义上看,这两个似乎 "say" 我想让他们做什么,但我没有得到任何清晰的结果。

有什么想法吗?

如果在一个 id-date 有两个观测值时总是有一个 L 和一个 R,就像您的示例数据一样,那么您可以像这样使用 duplicated

dat[duplicated(dat[-2]) | duplicated(dat[-2], fromLast = TRUE),]
   id eye       date
1   1   L 01-01-2000
2   1   L 01-06-2000
3   1   R 01-01-2000
5   1   R 01-06-2000
7   2   L 01-04-2000
8   2   R 01-04-2000
13  4   L 03-03-2001
14  4   R 03-03-2001

如果您需要检查 L 和 R 是否都存在于 id-date 对中,您可以保存以上结果并使用 ave 执行这样的检查

temp <- dat[duplicated(dat[-2]) | duplicated(dat[-2], fromLast = TRUE),]
temp[as.logical(ave(as.character(temp$eye), temp$id, temp$date,
                    FUN=function(x) all(x %in% c("L", "R")))),]
   id eye       date
1   1   L 01-01-2000
2   1   L 01-06-2000
3   1   R 01-01-2000
5   1   R 01-06-2000
7   2   L 01-04-2000
8   2   R 01-04-2000
13  4   L 03-03-2001
14  4   R 03-03-2001

对于 dplyr 你可以使用 filter:

dat %>%
  group_by(date) %>%
  filter(sum(eye == "L") > 0 & sum(eye == "R") > 0 & !(duplicated(date) & duplicated(eye)))

Source: local data frame [6 x 3]
Groups: date [3]

     id    eye       date
  <int> <fctr>     <fctr>
1     1      L 01-01-2000
2     1      L 01-06-2000
3     1      R 01-01-2000
4     1      R 01-06-2000
5     2      L 01-04-2000
6     2      R 01-04-2000

我们也可以用data.table

library(data.table)
setDT(df1)[,  .SD[(uniqueN(eye)>1) & !duplicated(eye)], date]
#         date id eye
#1: 01-01-2000  1   L
#2: 01-01-2000  1   R
#3: 01-06-2000  1   L
#4: 01-06-2000  1   R
#5: 01-04-2000  2   L
#6: 01-04-2000  2   R

另一个:

df <- read.table(header=TRUE, text="id    eye    date
1      L   01-01-2000
             1      L   01-06-2000
             1      R   01-01-2000
             1      R   01-03-2000
             1      R   01-06-2000
             2      L   01-01-2000
             2      L   01-04-2000
             2      R   01-04-2000
             2      R   01-07-2000
             2      R   04-09-2001
             3      L   01-01-2000
             4      L   01-01-2000
             4      L   03-03-2001
             4      R   03-03-2001")

library(dplyr)

left_join(df %>%
             group_by(id,date) %>%
             summarize(n=n()) %>%
             filter(n==2) %>%
             select(-n),
           df,
           by=c("id","date")) %>%
  arrange(id,eye,date)