首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >根据R中的B列使用data.table有条件删除与A列匹配的行

根据R中的B列使用data.table有条件删除与A列匹配的行
EN

Stack Overflow用户
提问于 2014-11-26 21:11:47
回答 3查看 432关注 0票数 3

试图在R中使用data.table解决一个去复制问题。

列A是一个名称列表,其中一些名称多次出现。B栏是日期列表。还有一堆其他的专栏,我也想复制(那些碰巧在日期上被命名的东西)。

但是,我只想查看新datatable中每个人的最多活动,该数据表中的每个名称都有一个条目,对应于最近的日期。

示例数据

代码语言:javascript
复制
    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()删除重复项,因为所有键都是唯一的。

这个问题类似于这里的一个帖子:Collapsing data frame by selecting one row per group。但是,我不能假设要选择的数据是第一次或最后一次,除非您可以在设置键后建议一种操作我的数据的方法。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-12-02 17:34:23

在不对数据表进行排序的情况下,有很多方法可以做到这一点(尽管排序是首选的,因为duplicated非常高效,而且您也避免使用by --会达到这个目的)。

首先,您必须确保date属于Date类,这样才能使事情变得更简单。

代码语言:javascript
复制
dt[, date := as.Date(date)]

第一个简单的方法(虽然不是最有效的)

代码语言:javascript
复制
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),应该是最有效的方法

代码语言:javascript
复制
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 (正如您已经做过的) ans在duplicated中指定from.last = TRUE和删除!来实现相同的目标。

代码语言:javascript
复制
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.tableunique函数(这也应该非常有效)。

代码语言:javascript
复制
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。这是效率最低的,但在某些情况下是有用的,因为您希望得到所有的列,并且不能使用这样的函数(如sduplicated )

代码语言:javascript
复制
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
票数 3
EN

Stack Overflow用户

发布于 2014-12-02 17:16:36

如果我理解您的问题,我认为您可以更清楚地使用sqldf包,但缺点是您必须了解sql。

代码语言:javascript
复制
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")

希望这能帮上忙。

票数 2
EN

Stack Overflow用户

发布于 2014-11-26 22:04:31

在写这篇文章的时候,我想出了办法。为了子孙后代..。

按名称和日期对表进行排序,以便您可以依赖于您希望成为组中的第一个或最后一个的日期。例如:dt[order(names,-date)]

然后,与其设置一个键并使用unique(),不如简单地:

dt[!duplicated(names)]

其中names是复制的列。

应该输出所需的表。如果有更优雅/可靠的方法来做这件事,我会有兴趣听到他们。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27159115

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档