对于按站点分组的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
Run Code Online (Sandbox Code Playgroud)
期望的结果是更改每个组中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
Run Code Online (Sandbox Code Playgroud)
似乎应该使用.I和/或.N,但我还没有找到一个有效的表单.在与.I [.N]相同的语句中使用:=会产生错误.以下给出了要进行赋值的行号:
DT[, .I[.N], by=site]
# site V1
# 1: A 5
# 2: B 9
Run Code Online (Sandbox Code Playgroud)
但我似乎无法使用:=赋值.以下给出了错误:
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)
Run Code Online (Sandbox Code Playgroud)
有没有办法通过data.table中的引用来做到这一点?或者在R中用另一种方式做得更好?
mne*_*nel 18
目前你可以使用
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)
Run Code Online (Sandbox Code Playgroud)
替代方法:
用replace...
DT[, a := replace(a, .N, 999), by = site]
Run Code Online (Sandbox Code Playgroud)
或者将替换转移到RHS,包裹{}并返回完整的向量
DT[, a := {a[.N] <- 999L; a}, by = site]
Run Code Online (Sandbox Code Playgroud)
或使用mult='last'和利用by-without-by.这要求data.table由感兴趣的组键入.
DT[unique(site), a := 999, mult = 'last']
Run Code Online (Sandbox Code Playgroud)
有一个功能请求#2793允许
DT[, a[.N] := 999]
Run Code Online (Sandbox Code Playgroud)
但这还没有实施