从sapply / lapply返回多个值

时间:2015-07-17 08:25:42

标签: r lapply sapply

我是R的新手并试图用apply系列中的fuction替换一些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)
                })

              })

这个想法是“循环”通过“热”data.frame的列并执行一些计算 来自“热”data.frame的值。出于这个原因,我使用第一个sapply功能来获得相应的功能 来自技术表的热量表中每个植物的特征。然后第二个sapply执行 计算。输出“结果”正是我想要的。

现在我想计算“热量”(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)
              })

感谢任何帮助或评论。

3 个答案:

答案 0 :(得分:6)

我建议你先整理一下你的数据。 see the tidyr package for more information

然后合并两个数据帧,您将不再需要任何循环或*应用函数。您只需在这个新数据框中进行计算,例如使用dplyr包:

library(tidyr)
library(dplyr)

heat %>%
  gather(id, value) %>%
  left_join(tech, by="id") %>%
  mutate(a = value * capacity.el,
         b = value * capacity.th)

答案 1 :(得分:3)

XNamespace ns = "http://schemas.microsoft.com/wix/2006/wi";
var x = doc.Root.Element(ns + "Directory");
x.Remove();
doc.Root.Add(x.Elements());

答案 2 :(得分:2)

使用data.table的可能选项(类似于@ user2992199&#d; dplyr方法)。我们转换了&#39; data.frame&#39;到&#39; data.table&#39; (setDT(heat)),改变广泛的&#39;长期&#39;格式为melt,将密钥设置为&#39; id&#39; (setkey(..., id)),加入&#39; tech&#39;,并创建列&#39; a&#39;和&#39; b&#39;。

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)][]