How to sum list items with the same name?

I am looking for a solution to this problem: I have a list of such lists

sample = list("element1" = list("term1"=0.5, "term2"=1, "term3"= 4, "term1"= 0.5), "element2" = list("term23"=5, "term1"=2, "term23"=4)) 

For each list of the external list, I would like to summarize the values ​​with the same name. Thus, the desired result

 desired_output = list("element1" = list("term1"=1, "term2"=1, "term3"= 4), "element2" = list("term23"=9, "term1"=2)) 

Actually, I was thinking of using something like this

 result = lapply(sample, function(l) aggregate(l, by = list(names(l)), FUN = sum)) 

but it gives me an error. Any ideas on this? Thanks in advance.

+5
source share
5 answers

Try the following:

 lapply(sample, function(y) {lapply(split(y,names(y)), function(x) {Reduce("+", x) })}) 

Output:

 $element1 $element1$term1 [1] 1 $element1$term2 [1] 1 $element1$term3 [1] 4 $element2 $element2$term1 [1] 2 $element2$term23 [1] 9 

Hope this helps!

+3
source

If you want to use aggregate , here is an idea that produces a slightly different result than your expected

 lapply(sample, function(i){s1 <- stack(unlist(i)); aggregate(values ~ ind, s1, sum)}) #or all in one line (compliments of Ronak Shah) lapply(sample, function(x) aggregate(values~ind, stack(x), sum)) #Or use xtabs to output your expected result (compliments of akrun) lapply(sample, function(x) as.list(xtabs(values~ind, stack(x)))) 

what gives,

 $element1 ind values 1 term1 1 2 term2 1 3 term3 4 $element2 ind values 1 term23 9 2 term1 2 
+4
source

We can loop through list , unlist and use one of the operation groups

 lapply(sample, function(x) { x1 <- unlist(x) as.list(tapply(x1, names(x1), FUN = sum)) }) #$element1 #$element1$term1 #[1] 1 #$element1$term2 #[1] 1 #$element1$term3 #[1] 4 #$element2 #$element2$term1 #[1] 2 #$element2$term23 #[1] 9 
+3
source

Other options for a double loop with sapply , where we find matching names in each list and sum their values.

 sapply(sample, function(x) sapply(unique(names(x)), function(y) sum(unlist(x[names(x) == y])))) #$element1 #term1 term2 term3 # 1 1 4 #$element2 #term23 term1 # 9 2 

If you want to save them in a list of lists. Use lapply .

+2
source

purrr::map_df simplifies simplifying this list to a neat data frame that is trivial for aggregation:

 library(tidyverse) sample = list(element1 = list(term1 = 0.5, term2 = 1, term3 = 4, term1 = 0.5), element2 = list(term23 = 5, term1 = 2, term23 = 4)) sample %>% map_dfr(~data_frame(name = names(.x), x = simplify(.x)), .id = 'element') %>% group_by(element, name) %>% summarise_all(sum) #> # A tibble: 5 x 3 #> # Groups: element [?] #> element name x #> <chr> <chr> <dbl> #> 1 element1 term1 1.00 #> 2 element1 term2 1.00 #> 3 element1 term3 4.00 #> 4 element2 term1 2.00 #> 5 element2 term23 9.00 
+1
source

Source: https://habr.com/ru/post/1274521/


All Articles