return 来自 sapply/lapply 的多个值
return multiple values from sapply/lapply
我是 R 的新手,正在尝试用 apply 系列的函数替换一些 for 循环。
我仍然不完全理解它们是如何工作的,但我设法生成了一段有效的代码:
#create some input data
tech<-data.frame(cbind(c("p1","p2","p3","p4"),c(15,15,15,100),c(10,8,18,100)))
colnames(tech)=c("id","capacity.el","capacity.th")
tech$capacity.el<-as.numeric(tech$capacity.el)
tech$capacity.th<-as.numeric(tech$capacity.th)
heat<-data.frame(cbind(c(2,12,6,20,32,21,25,16,34,0),c(31,18,3,27,30,31,18,4,24,7),c(2,12,6,20,32,21,25,16,34,0),c(31,18,3,27,30,31,18,4,24,7)))
colnames(heat)=c("p1","p2","p3","p4")
> tech
id capacity.el capacity.th
1 p1 2 1
2 p2 2 4
3 p3 2 3
4 p4 1 2
> heat
p1 p2 p3 p4
1 2 31 2 31
2 12 18 12 18
3 6 3 6 3
4 20 27 20 27
5 32 30 32 30
6 21 31 21 31
7 25 18 25 18
8 16 4 16 4
9 34 24 34 24
10 0 7 0 7
#the result should be a matrix/list
pel=matrix(,nrow=nrow(heat),ncol=ncol(heat))
epr=matrix(,nrow=nrow(heat),ncol=ncol(heat))
result<-list()
#main code
result<-sapply(colnames(heat),function(x) {
a<-tech$capacity.th[match(x,tech$id)]
b<-tech$capacity.el[match(x,tech$id)]
sapply(heat[,x],function(y) {
pel<-a*y
return(pel)
})
})
想法是 "loop" 通过 "heat" data.frame 的列并执行一些计算
来自 "heat" data.frame 的值。出于这个原因,我使用第一个 sapply 函数来获得相应的
来自技术 table 的热量 table 中每种植物的特征。第二个 sapply 然后执行
计算。输出 "result" 正是我想要的。
现在我想从 "heat"(pel 和 epr)中的每一行计算更多的值。
但我不知道如何从 sapply 函数中提取这些值。
我尝试了以下列表,但这将值提取为一个包含 20 行的大矩阵。
完美的结果应该是一个包含两个矩阵或 data.frame 对象的列表,每个对象有 10 行和 4 列
具有 pel/epr 个值。
result<-sapply(colnames(heat),function(x) {
a<-tech$capacity.th[match(x,tech$id)]
b<-tech$capacity.el[match(x,tech$id)]
sapply(heat[,x],function(y) {
pel<-a*y
epr<-b*y
})
new<-list(pel,epr)
return(new)
})
如有任何帮助或评论,我将不胜感激。
o <- match(tech$id,names(heat)); ## precompute tech row order to match heat column order
ms <- names(tech[-1]); ## store multiplier column names from tech
setNames(lapply(ms,function(m) t(t(heat)*tech[o,m])),ms);
## $capacity.el
## p1 p2 p3 p4
## [1,] 4 62 4 31
## [2,] 24 36 24 18
## [3,] 12 6 12 3
## [4,] 40 54 40 27
## [5,] 64 60 64 30
## [6,] 42 62 42 31
## [7,] 50 36 50 18
## [8,] 32 8 32 4
## [9,] 68 48 68 24
## [10,] 0 14 0 7
##
## $capacity.th
## p1 p2 p3 p4
## [1,] 2 124 6 62
## [2,] 12 72 36 36
## [3,] 6 12 18 6
## [4,] 20 108 60 54
## [5,] 32 120 96 60
## [6,] 21 124 63 62
## [7,] 25 72 75 36
## [8,] 16 16 48 8
## [9,] 34 96 102 48
## [10,] 0 28 0 14
我建议你先整理一下你的数据。 see the tidyr package for more information
然后合并两个数据帧,不需要任何循环或 *apply 函数。您只需在这个新数据框中进行计算,例如使用 dplyr 包:
library(tidyr)
library(dplyr)
heat %>%
gather(id, value) %>%
left_join(tech, by="id") %>%
mutate(a = value * capacity.el,
b = value * capacity.th)
使用 data.table
的可能选项(与 @user2992199 的 dplyr 方法类似的方法)。我们把'data.frame'转成'data.table'(setDT(heat)
),把'wide'转成'long'格式,用melt
,设置key为'id' (setkey(..., id)
),加入 'tech',并创建列 'a' 和 'b'.
library(data.table)#v1.9.5+
setkey(melt(setDT(heat), variable.name='id'), id)[tech
][, c('a', 'b') := list(value*capacity.el, value*capacity.th)][]
我是 R 的新手,正在尝试用 apply 系列的函数替换一些 for 循环。 我仍然不完全理解它们是如何工作的,但我设法生成了一段有效的代码:
#create some input data
tech<-data.frame(cbind(c("p1","p2","p3","p4"),c(15,15,15,100),c(10,8,18,100)))
colnames(tech)=c("id","capacity.el","capacity.th")
tech$capacity.el<-as.numeric(tech$capacity.el)
tech$capacity.th<-as.numeric(tech$capacity.th)
heat<-data.frame(cbind(c(2,12,6,20,32,21,25,16,34,0),c(31,18,3,27,30,31,18,4,24,7),c(2,12,6,20,32,21,25,16,34,0),c(31,18,3,27,30,31,18,4,24,7)))
colnames(heat)=c("p1","p2","p3","p4")
> tech
id capacity.el capacity.th
1 p1 2 1
2 p2 2 4
3 p3 2 3
4 p4 1 2
> heat
p1 p2 p3 p4
1 2 31 2 31
2 12 18 12 18
3 6 3 6 3
4 20 27 20 27
5 32 30 32 30
6 21 31 21 31
7 25 18 25 18
8 16 4 16 4
9 34 24 34 24
10 0 7 0 7
#the result should be a matrix/list
pel=matrix(,nrow=nrow(heat),ncol=ncol(heat))
epr=matrix(,nrow=nrow(heat),ncol=ncol(heat))
result<-list()
#main code
result<-sapply(colnames(heat),function(x) {
a<-tech$capacity.th[match(x,tech$id)]
b<-tech$capacity.el[match(x,tech$id)]
sapply(heat[,x],function(y) {
pel<-a*y
return(pel)
})
})
想法是 "loop" 通过 "heat" data.frame 的列并执行一些计算 来自 "heat" data.frame 的值。出于这个原因,我使用第一个 sapply 函数来获得相应的 来自技术 table 的热量 table 中每种植物的特征。第二个 sapply 然后执行 计算。输出 "result" 正是我想要的。
现在我想从 "heat"(pel 和 epr)中的每一行计算更多的值。 但我不知道如何从 sapply 函数中提取这些值。 我尝试了以下列表,但这将值提取为一个包含 20 行的大矩阵。 完美的结果应该是一个包含两个矩阵或 data.frame 对象的列表,每个对象有 10 行和 4 列 具有 pel/epr 个值。
result<-sapply(colnames(heat),function(x) {
a<-tech$capacity.th[match(x,tech$id)]
b<-tech$capacity.el[match(x,tech$id)]
sapply(heat[,x],function(y) {
pel<-a*y
epr<-b*y
})
new<-list(pel,epr)
return(new)
})
如有任何帮助或评论,我将不胜感激。
o <- match(tech$id,names(heat)); ## precompute tech row order to match heat column order
ms <- names(tech[-1]); ## store multiplier column names from tech
setNames(lapply(ms,function(m) t(t(heat)*tech[o,m])),ms);
## $capacity.el
## p1 p2 p3 p4
## [1,] 4 62 4 31
## [2,] 24 36 24 18
## [3,] 12 6 12 3
## [4,] 40 54 40 27
## [5,] 64 60 64 30
## [6,] 42 62 42 31
## [7,] 50 36 50 18
## [8,] 32 8 32 4
## [9,] 68 48 68 24
## [10,] 0 14 0 7
##
## $capacity.th
## p1 p2 p3 p4
## [1,] 2 124 6 62
## [2,] 12 72 36 36
## [3,] 6 12 18 6
## [4,] 20 108 60 54
## [5,] 32 120 96 60
## [6,] 21 124 63 62
## [7,] 25 72 75 36
## [8,] 16 16 48 8
## [9,] 34 96 102 48
## [10,] 0 28 0 14
我建议你先整理一下你的数据。 see the tidyr package for more information
然后合并两个数据帧,不需要任何循环或 *apply 函数。您只需在这个新数据框中进行计算,例如使用 dplyr 包:
library(tidyr)
library(dplyr)
heat %>%
gather(id, value) %>%
left_join(tech, by="id") %>%
mutate(a = value * capacity.el,
b = value * capacity.th)
使用 data.table
的可能选项(与 @user2992199 的 dplyr 方法类似的方法)。我们把'data.frame'转成'data.table'(setDT(heat)
),把'wide'转成'long'格式,用melt
,设置key为'id' (setkey(..., id)
),加入 'tech',并创建列 'a' 和 'b'.
library(data.table)#v1.9.5+
setkey(melt(setDT(heat), variable.name='id'), id)[tech
][, c('a', 'b') := list(value*capacity.el, value*capacity.th)][]