按日期和ID过滤重复项

时间:2017-05-04 18:53:21

标签: r dataframe filter duplicates

我有一个如下所示的数据框

Id      Date1        Date2        QuestionId   AnswerValue
10      2000-01-14   2000-01-14   1339         3
10      2000-01-14   1999-12-09   1339         2
10      2000-01-14   1999-11-23   1461         1 
10      2000-01-14   2000-01-03   1461         18
10      2000-01-14   1999-11-16   274          0
57      2014-02-01   2014-12-10   278          0
57      2014-02-01   2012-11-07   280          0
57      2014-02-01   2012-09-30   280          0 
57      2014-02-01   2012-01-15   261          0 

我的目标是根据以下标准保留观察结果。

1)保留该ID和QuestionID组合的行,其中QuestionID是唯一的,并且该ID + QuestionID组合没有其他重复的QuestionID。示例:保留最后一行

Id      Date1        Date2        QuestionId   AnswerValue
57      2014-02-01   2012-01-15   261          0 

2)如果每个QuestionID + ID组合都有重复的QuestionID,则只保留带有QuestionID的行,其中Date2列值最接近Date1列值,例如:Id 10有两个QuestionID 1339.根据此条件仅限1应保留行,因为问题ID 1339的Date2值2000-01-14最接近Date1值2000-01-14,而Date2值为1999-12-09的第二行与Date1值2000-01-相比较14。

Id      Date1        Date2        QuestionId   AnswerValue
10      2000-01-14   2000-01-14   1339         3

3)删除Date2值大于Date1的所有行。例如,应删除第6行

Id      Date1        Date2        QuestionId   AnswerValue
57      2014-02-01   2014-12-10   278          0

最终数据集如下所示。

Id      Date1        Date2        QuestionId   AnswerValue
10      2000-01-14   2000-01-14   1339         3
10      2000-01-14   2000-01-03   1461         18
10      2000-01-14   1999-11-16   274          0
57      2014-02-01   2014-12-10   278          0
57      2014-02-01   2012-11-07   280          0
57      2014-02-01   2012-01-15   261          0 

非常感谢任何帮助实现这一目标。提前谢谢。

2 个答案:

答案 0 :(得分:3)

以下是使用dplyr

的想法
library(dplyr)

df %>% 
  group_by(Id, QuestionId) %>% 
  slice(which.min(difftime(Date1, Date2))) %>% 
  filter(Date2 <= Date1)

#Source: local data frame [5 x 5]
#Groups: Id, QuestionId [5]

#     Id      Date1      Date2 QuestionId AnswerValue
#  <int>     <date>     <date>      <int>       <int>
#1    10 2000-01-14 1999-11-16        274           0
#2    10 2000-01-14 2000-01-14       1339           3
#3    10 2000-01-14 2000-01-03       1461          18
#4    57 2014-02-01 2012-01-15        261           0
#5    57 2014-02-01 2012-11-07        280           0

注意

确保您的日期列设置为as.Date

答案 1 :(得分:1)

使用$MapMarkers = array_reverse( $MapMarkers ); ,首先过滤标准3(data.table),然后只返回Date2 <= Date1最小的行(即日期彼此最接近),并使用Date1 - Date2by = .(Id, QuestionId)Id的每个独特组合执行此操作:

QuestionId

请注意,在您的最终数据示例中,此行不符合您的第三个条件(library(data.table) dt <- structure(list(Id = c(10L, 10L, 10L, 10L, 10L, 57L, 57L, 57L, 57L), Date1 = structure(c(10970, 10970, 10970, 10970, 10970, 16102, 16102, 16102, 16102), class = "Date"), Date2 = structure(c(10970, 10934, 10918, 10959, 10911, 16414, 15651, 15613, 15354), class = "Date"), QuestionId = c(1339L, 1339L, 1461L, 1461L, 274L, 278L, 280L, 280L, 261L), AnswerValue = c(3L, 2L, 1L, 18L, 0L, 0L, 0L, 0L, 0L)), .Names = c("Id", "Date1", "Date2", "QuestionId", "AnswerValue"), row.names = c(NA, -9L), class = "data.frame") setDT(dt) dt[Date2 <= Date1, .SD[which.min(Date1-Date2)], by = .(Id, QuestionId)] Id QuestionId Date1 Date2 AnswerValue 1: 10 1339 2000-01-14 2000-01-14 3 2: 10 1461 2000-01-14 2000-01-03 18 3: 10 274 2000-01-14 1999-11-16 0 4: 57 280 2014-02-01 2012-11-07 0 5: 57 261 2014-02-01 2012-01-15 0 ):

Date2 <= Date1