根据分类变量查找数据集中的公共日期

时间:2017-05-11 13:03:29

标签: r dplyr plyr

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

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"])))

从语义上讲,这两者似乎都“说”了我希望他们做什么,但我没有得到任何清晰的结果。

有什么想法吗?

4 个答案:

答案 0 :(得分:3)

如果对于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

如果您需要检查ID和日期对中是否存在L和R,您可以保存上述结果并使用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

答案 1 :(得分:3)

我们也可以使用ui error message

data.table

答案 2 :(得分:2)

使用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

答案 3 :(得分:1)

另一个:

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)