我有一个data.table或data.frame,如下所示:
Name Person Date
A 1 1/1/2004
A 2 1/1/2004
A 2 1/3/2004
A 3 1/1/2004
A 3 1/3/2004
A 3 1/9/2004
B 4 1/7/2004
B 5 1/7/2004
B 5 1/10/2004
B 6 1/7/2004
B 6 1/10/2004
B 6 1/17/2004
在这里,我正在尝试创建一个具有" NA"对于日期,如果他们不是最大的人。基本上,我试图让数据表看起来像:
Name Person Date
A 1 1/1/2004
A 2 "NA"
A 2 1/3/2004
A 3 "NA"
A 3 "NA"
A 3 1/9/2004
B 4 1/7/2004
B 5 "NA"
B 5 1/10/2004
B 6 "NA"
B 6 "NA"
B 6 1/17/2004
基本上,我想到的算法是按人看每个分组。如果按人分组只有一个元素,则该值为最大值,因此我们将其保留在那里。但是,例如,在按人2分组时,最大值是1/3/2004,所以我们让1/1/2004为" NA"。
我能想到这样做的唯一方法是找到与组(Person)的最大值对应的数据表的索引,然后创建所有NA的新向量,然后替换为最大值的索引。
代码如下:
which.max(data$Date, by=data$Person)
这对我来说不起作用,但无论哪种方式,这段代码看起来都可能是时间密集的,特别是如果我的数据集是1亿行。是否可以快速实现大型数据集,尤其是在data.table包中工作?谢谢!
答案 0 :(得分:4)
使用data.table
:
#dat <- as.data.table(dat)
#dat$Date <- as.Date(dat$Date,format="%m/%d/%Y")
dat[dat[, Date != max(Date) , by=Person][,V1], Date := NA]
dat
# Name Person Date
#1: A 1 2004-01-01
#2: A 2 <NA>
#3: A 2 2004-01-03
#4: A 3 <NA>
#5: A 3 <NA>
#6: A 3 2004-01-09
#7: B 4 2004-01-07
#8: B 5 <NA>
#9: B 5 2004-01-10
#10: B 6 <NA>
#11: B 6 <NA>
#12: B 6 2004-01-17
答案 1 :(得分:3)
这是ave()
的一个很好的用例,它允许您将函数应用于每个人的值。如果这是您的样本数据
dd<-structure(list(Name = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L,
2L, 2L, 2L, 2L, 2L), .Label = c("A", "B"), class = "factor"),
Person = c(1L, 2L, 2L, 3L, 3L, 3L, 4L, 5L, 5L, 6L, 6L, 6L
), Date = structure(c(12418, 12418, 12420, 12418, 12420,
12426, 12424, 12424, 12427, 12424, 12427, 12434), class = "Date")),
.Names = c("Name", "Person", "Date"),
row.names = c(NA, -12L), class = "data.frame")
然后使用
with(dd, ave(Date, Person,FUN=function(x) {x[x!=max(x)]<-NA; x}))
# [1] "2004-01-01" NA "2004-01-03" NA NA
# [6] "2004-01-09" "2004-01-07" NA "2004-01-10" NA
# [11] NA "2004-01-17"
答案 2 :(得分:3)
使用data.table
的另一种方式(假设每组没有多个最大值)
dat[dat[, order(Date)!=.N, by=Person]$V1, Date:= NA]
dat
# Name Person Date
#1: A 1 2004-01-01
#2: A 2 <NA>
#3: A 2 2004-01-03
#4: A 3 <NA>
#5: A 3 <NA>
#6: A 3 2004-01-09
#7: B 4 2004-01-07
#8: B 5 <NA>
#9: B 5 2004-01-10
#10: B 6 <NA>
#11: B 6 <NA>
#12: B 6 2004-01-17
如果您有多个最大值:
dat[dat[, rank(Date,ties.method="max")!=.N, by=Person]$V1, Date:=NA]
格式化date
dat[dat[, order(Date)!=.N, by=Person]$V1, Date:= NA][,Date:=format(Date, "%m/%d/%Y")]