重新排序数据表

时间:2016-10-27 10:24:40

标签: r sorting data.table

我正在寻找一种方法,以有效的方式对alphatical顺序的data.table的每一行进行重新排序。因此,我假设每列确实提供相同的信息并且具有可比性。当你看到这个例子时会更有意义:

test <- data.table(A = c("A", "b", "c"), 
                   B = c(1,"a","d"), 
                   C = c("F", 0, 1))

预期结果:

result <- data.table(t(apply(test,1, sort))) 
names(result) <- colnames(test)

在这个解决方案中,我必须遍历所有行,这可以防止吗? 对于2列,我找到了解决此问题的有效方法:

result <- data.table(A = pmin(test$A, test$B), B = pmax(test$A, test$B) )

但是这个解决方案不适用于超过2列

编辑:

让我们在两列上添加不同解决方案的基准:

test <- data.table(A = sample(c("A","B", "C", "D"), 1000000, replace = T),
                   B =  sample(c("A","B", "C", "D"), 1000000, replace = T))
OptionOne <- function(test){
  result <- data.table(A = pmin(test$A, test$B), B = pmax(test$A, test$B) )
}

OptionTwo <- function(test){
  test[, names(test) := as.list(sort(unlist(.SD))), 1:nrow(test)][]
}
OptionThree <- function(test){
  test[, id := .I]
  test <- melt(test, id.vars = "id")
  setorder(test, id, value) 
  test[, variable1 := seq_len(.N), by = id]
  dcast(test, id ~ variable1, value.var = "value")
}

system.time(OptionOne(test))
#user  system elapsed 
#0.13    0.00    0.12
system.time(OptionTwo(test))
#   user  system elapsed 
#  17.58    0.00   18.27
system.time(OptionThree(test))
#user  system elapsed 
# 0.23    0.00    0.24 

对于两列来说,pmin和pmax似乎是最有效的方式,但对于更多列,重塑可以很好地完成。

2 个答案:

答案 0 :(得分:2)

您的data.table在概念上形状错误。对行进行排序(即,对变量进行排序)没有意义。因此,要有效地做到这一点,你需要重塑:

library(data.table)
test <- data.table(A = c("A", "b", "c"), 
                   B = c(1,"a","d"), 
                   C = c("F", 0, 1))
test[, id := .I]

test <- melt(test, id.vars = "id")
setorder(test, id, value) 
#   id variable value
#1:  1        B     1
#2:  1        A     A
#3:  1        C     F
#4:  2        C     0
#5:  2        B     a
#6:  2        A     b
#7:  3        C     1
#8:  3        A     c
#9:  3        B     d

如果必须,你可以再次重塑,但我不建议这样做。

test[, variable1 := seq_len(.N), by = id]

dcast(test, id ~ variable1, value.var = "value")
#   id 1 2 3
#1:  1 1 A F
#2:  2 0 a b
#3:  3 1 c d

答案 1 :(得分:0)

我们可以尝试

test[, names(test) := as.list(sort(unlist(.SD))), 1:nrow(test)][]