Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

return multiple values from sapply/lapply

Tags:

r

lapply

sapply

I´m new to R and trying to replace some for loops with fuctions from the apply family. I still don´t understand totally how they work but I managed to produce a working piece of code:

#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)
                })

              })

The idea is to "loop" through the columns of the "heat" data.frame and perform some calculations with values from the "heat" data.frame. For this reason I use the first sapply fuction to get the corresponding characteristics for each of the plants in the heat table from the tech table. The second sapply then performs the calculations. The output "result" is exactly what I wanted.

Now I want to calculate more than value from each row in "heat" (pel and epr). But I have no idea how to extract these values from within the sapply fuctions. I tried the following with a list but this extracts the values as one large matrix with 20 rows. The perfect result would be something like a list with two matrix or data.frame objects that each have 10 rows and 4 columns with the pel/epr values.

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)
              })

I would appreciate any help or comment.

like image 514
derdepe Avatar asked Jul 17 '15 08:07

derdepe


Video Answer


1 Answers

I suggest you tidy up your data first. see the tidyr package for more information

Then you merge the two dataframes, and you won't need any loops or *apply functions. Your simply do your calculations within this new dataframe, for example by using the dplyr package:

library(tidyr)
library(dplyr)

heat %>%
  gather(id, value) %>%
  left_join(tech, by="id") %>%
  mutate(a = value * capacity.el,
         b = value * capacity.th)
like image 124
MarkusN Avatar answered Oct 13 '22 19:10

MarkusN