在 data.table 中,我们可以根据行号或条件选择行:
> x <- data.table(letters[1:4], 1:4)
> x
V1 V2
1: a 1
2: b 2
3: c 3
4: d 4
> x[2]
V1 V2
1: b 2
> x[V1 == "d"]
V1 V2
1: d 4
Run Code Online (Sandbox Code Playgroud)
但是我不能同时选择行号和条件:
> x[!2 & V2 > 1]
Empty data.table (0 rows) of 2 cols: V1,V2
Run Code Online (Sandbox Code Playgroud)
这可能是因为!2没有被解释为这种格式的行号。我知道我可以链接两个条件:
> x[!2][V2 > 1]
V1 V2
1: c 3
2: d 4
Run Code Online (Sandbox Code Playgroud)
但是我想为这个子集分配新的列值
x[!2][V2 > 1, V3 := "more"]
Run Code Online (Sandbox Code Playgroud)
现在它只为中间链接的 data.table 创建列。我可以保存中间表然后合并回原始表,但这会很麻烦。
其实我经常觉得data.table需要一个合适的行号。.I是一个依赖于组的动态数字,但我想要一个可以识别每一行的唯一 ID,这个唯一 ID 在合并/加入中非常有用(通常数据没有唯一 ID)。如果.i是行号,我可以使用
x[(.i != 2) & (V2 >1), V3 := "more"]
Run Code Online (Sandbox Code Playgroud)
我可以通过首先显式创建行号列来模拟这一点。
另一种方法是将子集 data.table 上的修改应用回原始表。假设我们有 x 作为原始表,x[!2] 作为一个子集,那么如果修改x[!2]实际上修改了 x,我的问题也将得到解决。当然,这种子集需要以不同的方式创建,例如x[!2, refOriginal = TRUE].
这是我对解决方案的两次尝试:第一个使用 的汇总语法data.table来计算逻辑向量,使用行号.I和位置处的条件来设置i子集和更新列;第二个使用which并setdiff从条件中删除某些行号,如果另一方面您需要and行号和条件的操作,setdiff可以替换为union:
x[x[, .I != 2 & V2 > 2], V3 := "more"]
x
# V1 V2 V3
# 1: a 1 NA
# 2: b 2 NA
# 3: c 3 more
# 4: d 4 more
x[setdiff(which(V2 > 2), c(2)), V3 := "more"]
x
# V1 V2 V3
# 1: a 1 NA
# 2: b 2 NA
# 3: c 3 more
# 4: d 4 more
Run Code Online (Sandbox Code Playgroud)