我试图找到一种方法来根据另一列中的值找到矩阵中列的最小值。假设我的矩阵看起来像这样:
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循环可能会起到作用,但是计算密集且昂贵。我想知道在创建具有最小值的列时是否有更简单的方法可以做到这一点。谢谢!
答案 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。)执行命令ave
和data.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