【问题标题】:Removing duplicates based on 3 columns in R基于R中的3列删除重复项
【发布时间】:2017-02-20 12:43:29
【问题描述】:

我有一个包含 30 万多个案例的数据集,其中一个客户 ID 可能会重复多次。每个客户也有一个与之相关的日期和等级。我希望能够只保留唯一的客户 ID,首先按日期排序,然后如果有重复日期的重复 ID,它将按排名排序(保持排名最接近 1)。我的数据示例如下:

Customer.ID  Date     Rank
576293     8/13/2012    2
576293     11/16/2015   6
581252     11/22/2013   4
581252     11/16/2011   6
581252     1/4/2016     5
581600     1/12/2015    3
581600     1/12/2015    2
582560     4/13/2016    1
591674     3/21/2012    6
586334     3/30/2014    1

理想的结果应该是这样的:

Customer.ID  Date     Rank
576293     11/16/2015   6
581252     1/4/2016     5
581600     1/12/2015    2
582560     4/13/2016    1
591674     3/21/2012    6
586334     3/30/2014    1

【问题讨论】:

  • 看来您应该对数据进行排序,然后使用unique()duplicated() 去除重复的ID。
  • 如果能通过dput函数提供样本数据就更好了。
  • 您的结果没有唯一的客户 ID
  • 你的问题不清楚。你能解释一下客户 ID 576293 和 581252 的输出吗?
  • df %>% mutate(Date = as.Date(Date, '%m/%d/%Y')) %>% group_by(Customer.ID) %>% arrange(desc(Date), Rank) %>% slice(1)

标签: r sorting duplicates


【解决方案1】:

明确了 OP 的期望输出:

我们也可以使用基本 R 来执行此操作,这将比使用 group_by(Customer.ID) 的以下 dplyr 方法更快,因为我们不必遍历所有唯一的 Customer.ID

df <- df[order(-df$Customer.ID,as.Date(df$Date, format="%m/%d/%Y"),-df$Rank, decreasing=TRUE),]
res <- df[!duplicated(df$Customer.ID),]

注意事项:

  1. 首先,按Customer.ID升序排序,然后Date降序排序,然后Rank升序排序。
  2. 删除Customer.ID 中的重复项,以便只保留每个Customer.ID 的第一行。

使用您发布的数据作为数据框df(不转换Date 列)以升序为Customer.ID 的结果:

print(res)
##   Customer.ID       Date Rank
##2       576293 11/16/2015    6
##5       581252   1/4/2016    5
##7       581600  1/12/2015    2
##8       582560  4/13/2016    1
##10      586334  3/30/2014    1
##9       591674  3/21/2012    6

数据:

df <- structure(list(Customer.ID = c(591674L, 586334L, 582560L, 581600L, 
581252L, 576293L), Date = c("3/21/2012", "3/30/2014", "4/13/2016", 
"1/12/2015", "1/4/2016", "11/16/2015"), Rank = c(6L, 1L, 1L, 
2L, 5L, 6L)), .Names = c("Customer.ID", "Date", "Rank"), row.names = c(9L, 
10L, 8L, 7L, 5L, 2L), class = "data.frame")

如果您只想保留每个 Customer.ID 的最新日期(后跟较低级别)行,您可以使用 dplyr 执行以下操作:

library(dplyr)
res <- df %>% group_by(Customer.ID) %>% arrange(desc(Date),Rank) %>% 
              summarise_all(funs(first)) %>%
              ungroup() %>% arrange(Customer.ID)

注意事项:

  1. group_by Customer.ID 并使用arrangeDate 降序排序,Rank 按升序排序。
  2. summarise_all 仅保留每个 Customer.ID 的第一行。
  3. 最后,ungroup 并按Customer.ID 排序以获得您想要的结果。

将您的数据用作数据框df,并将Date 列转换为Date 类:

print(res)
### A tibble: 7 x 3
##  Customer.ID       Date  Rank
##        <int>     <date> <int>
##1      576293 2015-11-16     6
##2      581252 2016-01-04     5
##3      581600 2015-01-12     2
##4      582560 2016-04-13     1
##5      586334 2014-03-30     1
##6      591674 2012-03-21     6

数据:

df <- structure(list(Customer.ID = c(576293L, 576293L, 581252L, 581252L, 
581252L, 581600L, 581600L, 582560L, 591674L, 586334L), Date = structure(c(15565, 
16755, 16031, 15294, 16804, 16447, 16447, 16904, 15420, 16159
), class = "Date"), Rank = c(2L, 6L, 4L, 6L, 5L, 3L, 2L, 1L, 
6L, 1L)), .Names = c("Customer.ID", "Date", "Rank"), row.names = c(NA, 
-10L), class = "data.frame")

【讨论】:

  • 这让我到了那里。棘手的部分是我需要日期降序和排名升序。由于我无法弄清楚如何一次对多种方式进行排序,因此我以相反的方向重新编码了“排名”(因此 1=6、2=5 等)然后您的代码运行良好。谢谢!
  • @J.Gorman:如果Ranknumeric,我发布的代码应该可以为您执行此操作,而无需重新编码Rank。这是因为它在order 中使用-df$Rankdecreasing=TRUE。请注意,我们需要在order 中使用decreasing=TRUE,因为-as.Date(...) 将不起作用。
猜你喜欢
  • 1970-01-01
  • 2016-12-02
  • 2021-11-03
  • 2021-01-31
  • 2018-12-27
  • 2012-05-19
  • 2015-09-30
  • 1970-01-01
相关资源
最近更新 更多