我想根据一些给定的索引顺序对data.table
的行进行重新排序,这就是setcolorder
对列的作用。有功能吗?
答案 0 :(得分:3)
neworder应该是新订单的“查找索引”,例如neworder = c(3,1,2)将第三行作为新的第一行,将第一行作为新的第二行,等等...
# example
DT = data.table(mtcars, keep.rownames=TRUE)[1:3]
ord = c(3,1,2)
DT
rn mpg cyl disp hp drat wt qsec vs am gear carb
1: Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
2: Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
3: Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
# use DT[ord, do_stuff]:
setorderv(DT[ord, .rn := .I], ".rn")[]
rn mpg cyl disp hp drat wt qsec vs am gear carb .rn
1: Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1 1
2: Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4 2
3: Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4 3
如评论中所述,我认为摆脱捕获行顺序的列是一个坏主意,但您可以像其他答案中那样包装一个包装来摆脱它。
如果1:.N
的行为发生了如下所述的变化,则可能需要在以后的版本中使用.I
:https://github.com/Rdatatable/data.table/issues/2598
答案 1 :(得分:2)
如果您的整数向量不是表固有的,那么我看不到自动执行该函数的函数(我希望其他人会喜欢,我不是data.table
-专家)。缺少这一点,这是一个快速的功能,烦人的message
调用显示对象内存地址,以表明此操作是在内部完成的(并且不更改内存位置):
setroworder <- function(DT, vec, verbose = TRUE, vecname = NA) {
if (is.logical(verbose)) verbose <- if (verbose) message else c
verbose("# ", data.table::address(DT))
if (is.na(vecname)) {
# find an unused name
vecname <- make.unique(c(colnames(DT), "vec"))[ ncol(DT) + 1L ]
}
verbose("# ", data.table::address(DT))
set(DT, i = NULL, j = vecname, value = order(vec))
verbose("# ", data.table::address(DT))
setorderv(DT, vecname)
verbose("# ", data.table::address(DT))
set(DT, j = vecname, value = NULL)
verbose("# ", data.table::address(DT))
invisible(DT) # convenience only, this function operates in side-effect
}
实际情况:
x <- data.table(a = 1:10)
setroworder(x, c(3,1,2,4:10))[]
# # 0000000012EFF1A8
# # 0000000012EFF1A8
# # 0000000012EFF1A8
# # 0000000012EFF1A8
# # 0000000012EFF1A8
# a
# 1: 3
# 2: 1
# 3: 2
# 4: 4
# 5: 5
# 6: 6
# 7: 7
# 8: 8
# 9: 9
# 10: 10
答案 2 :(得分:1)
修改。原始答案的行为不等于secolorder
。 neworder
应该是新顺序的“查找索引”,例如neworder = c(3, 1, 2)
将第三行作为新的第一行,将第一行作为新的第二行,等等...
这是我的解决方法:
setroworder <- function(x, neworder) {
# This is assumes that there is some convention that colnames do not start with '.'.
# I don't know if there is any such convention though.
x[, .indexcol := sort.int(neworder, index.return = TRUE)$ix]
setorder(x, .indexcol)
x[, .indexcol := NULL]
}
对其进行测试:
> x <- as.data.table(mtcars)
> head(x)
mpg cyl disp hp drat wt qsec vs am gear carb
1: 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
2: 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
3: 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
4: 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
5: 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
6: 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
> set.seed(42)
> head(setroworder(x, sample(32)))
mpg cyl disp hp drat wt qsec vs am gear carb
1: 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4
2: 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
3: 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
4: 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2
5: 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4
6: 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1