如何在data.table中通过引用更改每个组中的最后一个值

时间:2014-02-17 01:28:19

标签: r data.table

对于按站点分组的data.table DT,按时间t排序,我需要更改每个组中变量的最后一个值。我认为应该可以通过引用使用:=来做到这一点,但我还没有找到一种方法。

示例数据:

require(data.table)   # using 1.8.11 
DT <- data.table(site=c(rep("A",5), rep("B",4)),t=c(1:5,1:4),a=as.double(c(11:15,21:24)))
setkey(DT, site, t)
DT
#    site t  a
# 1:    A 1 11
# 2:    A 2 12
# 3:    A 3 13
# 4:    A 4 14
# 5:    A 5 15
# 6:    B 1 21
# 7:    B 2 22
# 8:    B 3 23
# 9:    B 4 24

所需的结果是更改每个组中a的最后一个值,例如更改为999,因此结果如下所示:

#    site t   a
# 1:    A 1  11
# 2:    A 2  12
# 3:    A 3  13
# 4:    A 4  14
# 5:    A 5 999
# 6:    B 1  21
# 7:    B 2  22
# 8:    B 3  23
# 9:    B 4 999

似乎应该使用.I和/或.N,但我找不到有效的表单。在与.I [.N]相同的语句中使用:=会产生错误。下面给出了要进行赋值的行号:

DT[, .I[.N], by=site]
#    site V1
# 1:    A  5
# 2:    B  9

但我似乎无法使用:=赋值。以下是错误:

DT[.N, a:=999, by=site]
# Null data.table (0 rows and 0 cols)

DT[, .I[.N, a:=999], by=site]
# Error in `:=`(a, 999) : 
#   := and `:=`(...) are defined for use in j, once only and in particular ways.
#  See help(":="). Check is.data.table(DT) is TRUE.

DT[.I[.N], a:=999, by=site]
# Null data.table (0 rows and 0 cols)

有没有办法在data.table中通过引用来做到这一点?或者在R中用另一种方式做得更好?

1 个答案:

答案 0 :(得分:14)

目前您可以使用

DT[DT[,.I[.N],by=site][['V1']],a:=999]
# or, avoiding the overhead of a second call to `[.data.table`
set(DT, i = DT[,.I[.N],by='site'][['V1']], j = 'a', value = 999L)

替代方法:

使用replace ...

DT[, a := replace(a,seq_len(.N)==.N,999) ,by=site]

或将替换转移到RHS,由{}包裹并返回完整的向量

DT[,a:={a[.N]<-999L; a},by=site]

或使用mult='last'并利用by-without-by。这要求data.table由感兴趣的组键入。

 DT[unique(site),a:=999,mult='last']

有一个功能请求#2793允许

DT[, a[.N] := 999]

但尚未实施