通过另一列中的值查找矩阵中列的最小值

时间:2014-07-29 20:11:56

标签: r

我试图找到一种方法来根据另一列中的值找到矩阵中列的最小值。假设我的矩阵看起来像这样:

A    B
3    1.2
3    3.4
3    0.7
4    4.5
4    4.9
5    0.1
5    0.4
6    5

我希望找到"本地最大值"对于在A中共享相同数字的每一列,B表示。

所以,我想得到一个新的变量C,看起来像:

A    B     C
3    1.2   0.7
3    3.4   0.7
3    0.7   0.7
4    4.5   4.5
4    4.9   4.5
5    0.1   0.1
5    0.4   0.1
6    5     5

可以看出,C中的值是B中条目的最小值,在A中共享相同的值。

for(i in 1:length(data)){

if (A[i]==A[i+1])
else C <- min(B[i])

}

上面这样的for循环可能会起到作用,但是计算密集且昂贵。我想知道在创建具有最小值的列时是否有更简单的方法可以做到这一点。谢谢!

4 个答案:

答案 0 :(得分:5)

有两种方法可以解决这个问题。最简单的是:

> data$C <- ave(data$B, data$A, FUN = min)
> d
  A   B   C
1 3 1.2 0.7
2 3 3.4 0.7
3 3 0.7 0.7
4 4 4.5 4.5
5 4 4.9 4.5
6 5 0.1 0.1
7 5 0.4 0.1
8 6 5.0 5.0

另一个是&#34; split-apply-combine&#34;策略。

答案 1 :(得分:4)

托马斯的答案很好。这在data.table中也很容易做到。

首先,生成数据并加载包:

a <- c(rep(1,10),rep(2,10),rep(3,10))
b <- rnorm(30,10,10)
test <- data.frame(a,b)
library(data.table)
setDT(test)

然后创建新列:

test[,c:=min(b),by=a]

结果:

     a            b          c
  1: 1 14.844139174 -5.7023026
  2: 1 23.415562328 -5.7023026
  3: 1 11.235909827 -5.7023026
  4: 1  3.157023269 -5.7023026
  5: 1 16.998426190 -5.7023026
  6: 1  2.610968522 -5.7023026
  7: 1 12.978947375 -5.7023026
  8: 1 -5.702302571 -5.7023026
  9: 1 15.497820331 -5.7023026
 10: 1 25.732043280 -5.7023026
 11: 2  4.141440090 -0.2139922
 12: 2 16.249885918 -0.2139922
 13: 2  4.644226740 -0.2139922
 14: 2 19.529676583 -0.2139922
 15: 2 -0.213992236 -0.2139922
 16: 2 24.080005586 -0.2139922
 17: 2  5.670197636 -0.2139922
 18: 2 28.791961411 -0.2139922
 19: 2  5.514285666 -0.2139922
 20: 2 14.711643377 -0.2139922
 21: 3  3.933511784 -0.1845652
 22: 3  2.159187044 -0.1845652
 23: 3 21.925758264 -0.1845652
 24: 3 15.572109856 -0.1845652
 25: 3  0.001924788 -0.1845652
 26: 3 20.288486370 -0.1845652
 27: 3 16.568929808 -0.1845652
 28: 3  2.180839713 -0.1845652
 29: 3 -0.184565166 -0.1845652
 30: 3  1.236794095 -0.1845652

在评论中,对setDT()<- data.table进行了简短讨论。 setDT()不会创建副本,因此比我在本文中最初使用的<-data.table内存效率更高。感谢David Arenburg提供的信息。

答案 2 :(得分:3)

我只是比较了为大数据集(10 mio。)执行命令avedata.table所需的时间。 有关我的计算机处理器的信息:Core i3,CPU M350 2.27Ghz

a <- gl(1000000,10)
b <- rnorm(length(a))
test <- data.frame(a,b)
library(data.table)
test <- data.table(test)


Rprof("Test")
l <- test[,c:=min(b),by=a]
Rprof(NULL)
head(summaryRprof("Test")$by.total, 5)
# --------------------------------------------------------
                   total.time total.pct self.time self.pct
".Call"              1.30    100.00      0.92    70.77
"["                  1.30    100.00      0.00     0.00
"[.data.table"       1.30    100.00      0.00     0.00
"min"                0.38     29.23      0.38    29.23
"forder"             0.16     12.31      0.00     0.00
# --------------------------------------------------------

Rprof("Test1")
test$c <- ave(test$b, test$a, FUN = min)
Rprof(NULL)
head(summaryRprof("Test1")$by.total, 5)
 # --------------------------------------------------------
                  total.time total.pct self.time self.pct
"ave"                   7.16     89.72      0.04     0.50
"split<-.default"       3.74     46.87      2.36    29.57
"split<-"               3.74     46.87      0.00     0.00
"lapply"                2.68     33.58      0.84    10.53
"split"                 1.50     18.80      0.00     0.00
"split.default"         1.48     18.55      1.48    18.55
"FUN"                   1.28     16.04      1.28    16.04
".Call"                 0.82     10.28      0.82    10.28
"$<-"                   0.82     10.28      0.00     0.00
"$<-.data.table"        0.82     10.28      0.00     0.00
 # --------------------------------------------------------

结论:data.table的效率是ave的5.5倍。

答案 3 :(得分:1)

dplyr解决方案

library(dplyr)
df %>% 
  group_by(A) %>%
    mutate(C = min(B))

# Source: local data frame [8 x 3]
# Groups: A
# 
#   A   B   C
# 1 3 1.2 0.7
# 2 3 3.4 0.7
# 3 3 0.7 0.7
# 4 4 4.5 4.5
# 5 4 4.9 4.5
# 6 5 0.1 0.1
# 7 5 0.4 0.1
# 8 6 5.0 5.0