【问题标题】:Reordering each row of a datatable重新排序数据表的每一行
【发布时间】:2016-10-27 10:24:40
【问题描述】:

我正在寻找一种方法,以一种有效的方式按字母顺序对 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 是最有效的方法,但对于更多列,reshape 效果很好。

【问题讨论】:

  • 将字符串与整数结合起来对我来说没有意义,而且很危险。你为什么要这样做?
  • 也许这个例子实际上是错误的,它们都是字符

标签: r sorting data.table


【解决方案1】:

您的 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

【讨论】:

    【解决方案2】:

    我们可以试试

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

    【讨论】:

    • 如果我将 2 列方法与 pmin 和 pmax 与此方法进行比较比 pmin 和 pmax 快得多,此方法确实会花费大量时间。
    猜你喜欢
    • 1970-01-01
    • 2016-04-12
    • 1970-01-01
    • 2019-11-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 2019-02-12
    相关资源
    最近更新 更多