如何重新排序data.table的列(无需复制)

147
我想重新排列data.table x中的列,给定一个字符向量neworder,该向量包含了新的列名。
library(data.table)
x <- data.table(a = 1:3, b = 3:1, c = runif(3))
neworder <- c("c", "b", "a")

显然,我可以这样做:

x[ , neworder, with = FALSE]
# or
x[ , ..neworder]
#            c b a
# 1: 0.8476623 3 1
# 2: 0.4787768 2 2
# 3: 0.3570803 1 3

但这将需要再次复制整个数据集。还有其他方法可以做到这一点吗?

2个回答

213

使用setcolorder()函数:

library(data.table)
x <- data.table(a = 1:3, b = 3:1, c = runif(3))
x
#      a b         c
# [1,] 1 3 0.2880365
# [2,] 2 2 0.7785115
# [3,] 3 1 0.3297416
setcolorder(x, c("c", "b", "a"))
x
#              c b a
# [1,] 0.2880365 3 1
# [2,] 0.7785115 2 2
# [3,] 0.3297416 1 3

来自?setcolorder

data.table术语中,所有的set*函数都是通过引用更改其输入。也就是说,除了临时工作内存(仅限一个列),不会进行任何复制。

因此,应该非常高效。有关详细信息,请参见?setcolorder


29
小澄清:setcolorder 只是移动列指针,根本不使用任何工作内存。关于使用与一列大小相同的工作内存的那句话只是在讲 setkey 而已。 - Matt Dowle
2
@MatthewDowle - 感谢您的澄清。我有点觉得那可能是情况,但不太确定。 - Chase
4
我可以为某些列进行这样的操作吗?例如当我只想将列移到最前面时? - Jakob
7
setcolorder(df, c("someCol",colnames(dt)[!(colnames(dt) %in% c("someCol"))])) - hedgedandlevered
12
@PeterPan 请注意开发版本1.10.5的新闻:"setcolorder()现在可以接受少于ncol(DT)列移动到前面"。 - Henrik
显示剩余2条评论

19

如果按列号排序,使用上述解决方案可能会更容易。例如: library(data.table)

    > x <- data.table(a = 1:3, b = 3:1, c = runif(3))
    > x
         a b         c
    [1,] 1 3 0.2880365
    [2,] 2 2 0.7785115
    [3,] 3 1 0.3297416
    > setcolorder(x, c(3,2,1))
    > x
         c         b a
    [1,] 0.2880365 3 1
    [2,] 0.7785115 2 2
    [3,] 0.3297416 1 3

19
在data.table和其他情境下,一般不鼓励使用列的编号进行引用。在这里数据表格(data.table)FAQ的第一项给出了理由:http://datatable.r-forge.r-project.org/datatable-faq.pdf - Frank

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接