salva
salva

Reputation: 10234

Summarize with a function that returns multiple values in a list

I have a function that receives two vectors and returns a list of parameters, similar to this one:

f <- function(x, n) {
    mu <- sum(x)/sum(n)
    max <- max(x/n)
    min <- min(x/n)
    return(list(mu = mu, max = max, min = min))
}

Now, I want to apply that function to a grouped dataframe and get back a new data frame with columns for mu, max, min and the grouping variable level.

I have tried to do it with summarize as follows:

data %>% group_by(level) %>% summarize(p=f(x=x, n=n))

But instead of a dataframe with fourth columns I get one with two columns, where the second one contains an entry for every parameter coming out for the function wrapped as one-element lists.

I can process that data frame to generate one in the format I want as follows:

data2 %>%
  transmute(level=level, col=names(p), value=p[[1]]) %>%
  pivot_wider(names_from=col, values_from=value)

But that looks quite convoluted and ugly, so, is there any simpler way to do it?

Update: Complete code:

n <- sample(100, size=10, replace=TRUE)
x <- rbinom(100, n, 0.5)
level <- sample(c("a", "b", "c"), 100, replace=TRUE)
data <- data.frame(level=level, x=x, n=n)

f <- function(x, n) {
    mu <- sum(x)/sum(n)
    max <- max(x/n)
    min <- min(x/n)
    return(list(mu = mu, max = max, min = min))
}

data2 <- data %>% group_by(level) %>% summarize(p=f(x=x, n=n))

data3 <- data2 %>%
    transmute(level=level, col=names(p), value=p[[1]]) %>%
    pivot_wider(names_from=col, values_from=value)

Upvotes: 1

Views: 904

Answers (1)

det
det

Reputation: 5232

you can do that by replacing return(list(mu = mu, max = max, min = min)) with return(tibble(mu = mu, max = max, min = min)) in your function f and using it like this:

df %>% group_by(group) %>% summarise(f(x, y))

where group is grouping variable, x and y are variables to be used in function f.

Upvotes: 2

Related Questions