【问题标题】:Filter duplicates by date and id按日期和 ID 过滤重复项
【发布时间】:2017-10-03 02:19:06
【问题描述】:

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

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,则仅保留 Date2 列值最接近 Date1 列值的 QuestionID 行,例如:ID 10 有两个 QuestionID 1339。根据此条件,仅保留第一个行应保留,因为与 Date2 值 1999-12-09 与 Date1 值 2000-01- 相比,问题 ID 1339 的 Date2 值 2000-01-14 最接近 Date1 值 2000-01-14 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 

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

【问题讨论】:

  • 您的第一个标准非常难以遵循。不应该保留第五行和第六行吗?您只想要一个独特的 Id+QuestionId 组合吗?如何在 Id+QuestionId 组合中存在唯一的 QuestionId 另一个具有相同 Id+QuestionId 组合的观察?

标签: r dataframe filter duplicates


【解决方案1】:

这是一个使用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

【讨论】:

    【解决方案2】:

    使用data.table,首先过滤您的标准3 (Date2 &lt;= Date1),然后只返回Date1 - Date2 最小的行(即日期彼此最接近),然后使用by = .(Id, QuestionId) 执行此操作对于IdQuestionId 的每个独特组合:

    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 &lt;= Date1):

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-05
      • 2022-01-26
      相关资源
      最近更新 更多