从lapply返回两个对象

时间:2017-06-16 03:43:55

标签: r function loops dplyr lapply

我创建了一个运行需要一段时间的函数(正在进行大量的运算),并且我需要从此函数返回两个不同的输出。这些输出的输入是相同的,这就是为什么我将它们组合在同一个函数中以便我不必将它们压缩两次,但是输出内容完全不同并且基于这样完全不同的计算没有办法真正将它们组合成一个解析的声明。一个对象比另一个对象早几十行。但我需要返回两者,所以我认为它必须是某种类型的模仿形式:将两个单独的对象存储在一个列表中,然后提取并重新绑定两个对象。

对此解决方案的任何帮助都将受到赞赏 - 理想情况下不使用for循环或data.table。 Dplyr解决方案很好。

一些虚拟数据:

func <- function(x, df){

    temp <- filter(df, ID == x)

    average_id <- temp %>% group_by(ID) %>% summarise(avg = mean(Val))
    average_subid <- temp %>% group_by(ID, subID) %>% summarise(avg = mean(Val))

    df_list <- list(avgID=average_id, avgSubID=average_subid)

    return(df_list)

}

该函数(再次注意到函数比这复杂得多,我在每个单独的对象中计算更复杂和无关的东西,而不仅仅是平均值!):

result <- lapply(list("A","B","C"), func, df)

目前我已使用此命令计算结果,但我不确定这是否正确或如何在对象存储在此列表(列表中)之后进一步提取结果(即我被卡在这里):

> average_ID
  ID avg
1  A 6.2
2  B 5.0
3  C 7.4


> average_subID
  ID subID   avg
1  A     U   4.8
2  A     V   7.6
3  B     W   4.2
4  B     X   5.8
5  C     Y   4.4
6  C     Z  10.4

结果如下:

{{1}}

我之前使用了for循环并将结果存储在列表中(即avgListID [x]&lt; - average_id,然后绑定在一起。但我不认为这是理想的。

提前致谢!

3 个答案:

答案 0 :(得分:1)

> average_ID <- aggregate(df$Val, by = list(df$ID), FUN = mean)
> 
> average_ID
  Group.1   x
1       A 6.2
2       B 5.0
3       C 7.4
> average_subID <- aggregate(df$Val, by = list(df$ID,df$subID), FUN = mean)
> 
> average_subID
  Group.1 Group.2    x
1       A       U  4.8
2       A       V  7.6
3       B       W  4.2
4       B       X  5.8
5       C       Y  4.4
6       C       Z 10.4

答案 1 :(得分:1)

我意识到这有点陈旧,但是既然没有提供的答案似乎都可以解决问题,那该怎么办?将函数拆分为两个,然后在lapply中运行每个函数,返回列表列表?

library(dplyr)

df <- data.frame(ID = c(rep("A",10), rep("B", 10), rep("C", 10)),
                 subID = c(rep("U", 5),rep("V", 5),rep("W", 5),rep("X", 5),rep("Y", 5),rep("Z", 5)),
                 Val = c(1,6,3,8,6,5,2,4,7,20,4,2,3,5,7,3,2,5,7,12,5,3,7,1,6,1,34,9,5,3))

subfunc1 <- function(temp){
  return(temp %>% group_by(ID) %>% summarise(avg = mean(Val)))
}

subfunc2 <- function(temp){
  return(temp %>% group_by(ID, subID) %>% summarise(avg = mean(Val)))
}

func <- function(x, df){

  temp <- filter(df, ID == x)

  df_list <- list(avgID=subfunc1(temp), avgSubID=subfunc2(temp))

  return(df_list)

}

result <- lapply(list("A","B","C"), func, df)

要获取所需的结构/顺序,请按照here的说明对列表进行转置:

n <- length(result[[1]]) # assuming all lists in result have the same length
result <- lapply(1:n, function(i) lapply(result, "[[", i))

答案 2 :(得分:0)

返回一个列表,其中每个元素代表特定分组级别的平均值。例如:

data.unstack().plot(kind='bar')
library(tidyverse)

fnc = function(groups=NULL, data=df) {

  groups=as.list(groups)

  data %>% 
    group_by_(.dots=groups) %>%
    summarise(avg=mean(Val))
}

list(Avg_Overall=NULL, Avg_by_ID="ID", Avg_by_SubID=c("ID","subID")) %>% 
  map(~fnc(.x))

您也可以按$Avg_Overall # A tibble: 1 x 1 avg <dbl> 1 6.2 $Avg_by_ID # A tibble: 3 x 2 ID avg <fctr> <dbl> 1 A 6.2 2 B 5.0 3 C 7.4 $Avg_by_SubID # A tibble: 6 x 3 # Groups: ID [?] ID subID avg <fctr> <fctr> <dbl> 1 A U 4.8 2 A V 7.6 3 B W 4.2 4 B X 5.8 5 C Y 4.4 6 C Z 10.4 计算平均值,然后根据subID计算平均值:

ID