[英]Conditionally remove rows that match in column A, based on column B in R using data.table
尝试使用R中的data.table来修复重复数据删除问题
列A是名称列表,其中一些出现多次。 B列是日期列表。 我还想复制其他一些列(发生在Name on Date上的事情。)
但是,我只想查看新数据表中每个人的最多活动,每个名称对应于最近的日期有1个条目。
示例数据
name.last date
1: Adams 2014-10-20
2: Adams 2014-07-07
3: Barnett 2014-11-06
4: Barnett 2014-09-22
5: Bell 2014-10-22
6: Bell 2014-07-29
7: Burns 2014-09-08
8: Burns 2014-09-03
9: Camacho 2014-08-12
10: Camacho 2014-07-08
11: Casillas 2014-10-07
12: Casillas 2014-07-17
13: Chavez 2014-09-23
14: Chavez 2014-09-17
15: Chavira 2014-07-15
16: Chavira 2014-07-07
17: Claren 2014-10-30
18: Claren 2014-10-23
19: Colleary 2014-11-11
20: Colleary 2014-11-07
答案只返回每个名字的第一个(因为这里的行按每个第一个的最新日期排序。)但是如果我设置dt键setkey(dt,name.last)
以便使用unique()
来删除重复项,它按键顺序重新排序表(按名称字母顺序)。 然后使用unique(dt)
返回每个名称的第一个外观,这不一定是最近的日期。
如果我在两个列setkeyv(dt,c(name.last,date))
设置密钥,那么我不能使用unique()
删除重复项,因为所有键都是唯一的。
问题类似于此处的一篇文章: 通过为每个组选择一行来折叠数据框 。 但是我不能假设要选择的数据是第一个还是最后一个,除非你可以建议一种操作我的数据的方法来设置密钥。
有许多这样做的方法没有订购数据表(虽然是首选排序,因为duplicated
是非常有效的,你也避免使用by
-将获得这一点)。
首先,您必须确保date
是Date
类,以便更轻松
dt[, date := as.Date(date)]
第一个简单的方法(虽然不是最有效的)
dt[, max(date), name.last]
# name.last V1
# 1: Adams 2014-10-20
# 2: Barnett 2014-11-06
# 3: Bell 2014-10-22
# 4: Burns 2014-09-08
# 5: Camacho 2014-08-12
# 6: Casillas 2014-10-07
# 7: Chavez 2014-09-23
# 8: Chavira 2014-07-15
# 9: Claren 2014-10-30
# 10: Colleary 2014-11-11
第二个(提供的)方法与您的类似,但是使用data.tables setorder
(对于data.table
版本> = 1.9.4)并且应该是最有效的
setorder(dt, name.last, -date)[!duplicated(name.last)]
# name.last date
# 1: Adams 2014-10-20
# 2: Barnett 2014-11-06
# 3: Bell 2014-10-22
# 4: Burns 2014-09-08
# 5: Camacho 2014-08-12
# 6: Casillas 2014-10-07
# 7: Chavez 2014-09-23
# 8: Chavira 2014-07-15
# 9: Claren 2014-10-30
# 10: Colleary 2014-11-11
您可以使用setkey
(就像您已经做过的那样)实现相同的setkey
,并在duplicated
和删除中指定from.last = TRUE
!
setkey(dt, name.last, date)[duplicated(name.last, from.last = TRUE)]
# name.last date
# 1: Adams 2014-10-20
# 2: Barnett 2014-11-06
# 3: Bell 2014-10-22
# 4: Burns 2014-09-08
# 5: Camacho 2014-08-12
# 6: Casillas 2014-10-07
# 7: Chavez 2014-09-23
# 8: Chavira 2014-07-15
# 9: Claren 2014-10-30
# 10: Colleary 2014-11-11
第三种方法是使用data.table
的unique
功能(也应该非常有效)
unique(setorder(dt, name.last, -date), by = "name.last")
# name.last date
# 1: Adams 2014-10-20
# 2: Barnett 2014-11-06
# 3: Bell 2014-10-22
# 4: Burns 2014-09-08
# 5: Camacho 2014-08-12
# 6: Casillas 2014-10-07
# 7: Chavez 2014-09-23
# 8: Chavira 2014-07-15
# 9: Claren 2014-10-30
# 10: Colleary 2014-11-11
最后一种方法是使用.SD
。 它效率最低,但在某些情况下,当您想要获取所有列并且不能使用duplicated
函数时,它很有用
setorder(dt, name.last, -date)[, .SD[1], name.last]
# name.last date
# 1: Adams 2014-10-20
# 2: Barnett 2014-11-06
# 3: Bell 2014-10-22
# 4: Burns 2014-09-08
# 5: Camacho 2014-08-12
# 6: Casillas 2014-10-07
# 7: Chavez 2014-09-23
# 8: Chavira 2014-07-15
# 9: Claren 2014-10-30
# 10: Colleary 2014-11-11
如果我理解你的问题,我认为你可以用sqldf包更干净地做到这一点,但缺点是你必须知道sql。
install.packages("sqldf")
library("sqldf")
dt <-data.frame(read.table(header = TRUE, text = " name.last date
1: Adams 2014-10-20
2: Adams 2014-07-07
3: Barnett 2014-11-06
4: Barnett 2014-09-22
5: Bell 2014-10-22
6: Bell 2014-07-29
7: Burns 2014-09-08
8: Burns 2014-09-03
9: Camacho 2014-08-12
10: Camacho 2014-07-08
11: Casillas 2014-10-07
12: Casillas 2014-07-17
13: Chavez 2014-09-23
14: Chavez 2014-09-17
15: Chavira 2014-07-15
16: Chavira 2014-07-07
17: Claren 2014-10-30
18: Claren 2014-10-23
19: Colleary 2014-11-11
20: Colleary 2014-11-07")
)
head(dt)
colnames(dt) <- c('names', 'date')
sqldf("select names, min(date), max(date) from dt group by names")
希望这很有帮助。
在写这篇文章时我发现了它。 后人......
按名称和日期对表格进行排序,以便您可以依赖于您希望在组中的第一个或最后一个日期。 例如: dt[order(names,-date)]
。
然后,而不是设置一个键并使用unique()
,只需一个简单的:
dt[!duplicated(names)]
names
是重复列。
应输出所需的表格。 如果有更优雅/可靠的方法来做到这一点,我会有兴趣听到它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.