【问题标题】:Efficiently Extract Minimum Value AND Index for Each Column and Row in a Dataframe, then Rank by Value有效提取数据框中每一列和每一行的最小值和索引,然后按值排序
【发布时间】:2014-05-04 01:04:09
【问题描述】:

我有一个 JxK 数据帧 M,我想计算以下内容。

  1. 对于每一行 j,最小化 M[j,k] 的值 k
  2. 对于每一列 k,最小化 M[j,k] 的值 j

然后,让满足第一个的值是向量A_j,第二个是向量A_k。然后,我需要两个向量。设向量 C 为向量 sort(c(A_j, A_k))。

  1. 长度等于 A_j 的向量,其中元素 i 是元素 A_j[i] 在组合和排序向量 C 中的索引。
  2. 长度等于 A_k 的向量,其中元素 i 是元素 A_k[i] 在组合和排序向量 C 中的索引。

对于上面提到的两个排序向量,所有的关系都应该被赋予该值在向量 C 中出现的第一个索引。也就是说,如果 A_j[i] 和 A_j[i+1] 相等,则元素向量中满足条件#3 的 i 和元素 i + 1 应该都等于 A_j[i] 在排序向量 C 中的位置。

与往常一样,这并不难做到低效。然而,在实践中,数据框非常大,因此低效的解决方案会失败。

作为概念证明,一种解决方案如下。

# Create the dataframe
set.seed(1)
df <- data.frame(matrix(rnorm(50, 8, 2), 10)) # A 10x5 matrix

# Calculate 1 and 2
A.j <- apply(df, 1, min) 
A.k <- apply(df, 2, min)

# Calculate 3 and 4
C <- sort(unname(c(A.j, A.k)))

A.j.indices <- apply(df, 1, function(x) which(x == min(x)))
A.k.indices <- apply(df, 2, function(x) which(x == min(x)))

vec3out <- c()
vec4out <- c()

for(j in 1:nrow(df)){
   rank <- which(C == A.j[j])[1] 
   vec3out <- c(vec3out, rank)
}

for(k in 1:ncol(df)){
   rank <- which(C == A.k[k])[1] 
   vec4out <- c(vec4out, rank)
}

【问题讨论】:

  • 请发布一个演示这些“低效方法”之一的最小示例 - 这对于验证更有效的解决方案是否正常工作以及对运行时进行基准测试非常重要。
  • 你用过which.minwhich.max吗?看起来直截了当且高效
  • @politicaleconomist match 来自发布的解决方案绝对看起来像您正在寻找的东西。您发布的解决方案位于R Inferno 的第二个圈子中。看看——这是一本好书!

标签: r algorithm sorting vector dataframe


【解决方案1】:

对于初学者,您应该使用矩阵。 Data.frames 效率较低 (Should I use a data.frame or a matrix?)。然后,我们应该使用 apply 函数。

让 M 成为你的 data.frame 强制转换为矩阵。

M <- as.matrix(M)

minByRow <- apply(M, MARGIN=1, FUN=which.min)
minByCol <- apply(M, MARGIN=2, FUN=which.min)

combinedSorted <- sort(c(minByRow, minByCol))

byRowOutput <- match(minByRow, combinedSorted)
byColOutput <- match(minByCol, combinedSorted)

以下是对 100 个变量进行 100 万次观察的结果:

M <- matrix(data=rnorm(100000000), nrow=1000000, ncol=100)


system.time({
  minByRow <- apply(M, MARGIN=1, FUN=which.min)
  minByCol <- apply(M, MARGIN=2, FUN=which.min)

  combinedSorted <- sort(c(minByRow, minByCol))

  byRowOutput <- match(minByRow, combinedSorted)
  byColOutput <- match(minByCol, combinedSorted)
})

   user  system elapsed 
   7.37    0.46    7.93 

【讨论】:

    猜你喜欢
    • 2015-01-09
    • 2015-05-30
    • 2014-10-11
    • 1970-01-01
    • 2020-12-23
    • 1970-01-01
    • 2021-07-18
    • 2016-04-13
    相关资源
    最近更新 更多