如何对具有相同名称的列表元素求和?

时间:2018-01-05 08:50:49

标签: r list sum aggregate lapply

我正在寻找这个问题的解决方案: 我有一个像这样的列表列表

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

对于外部列表的每个列表,我想对具有相同名称的值求和。所以期望的输出是

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

实际上,我想过要用这样的东西

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

但这给了我一个错误。 有关于此的任何想法? 提前谢谢。

5 个答案:

答案 0 :(得分:4)

如果你想使用aggregate,这个想法会产生一个与预期不同的输出

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

给出,

$element1
    ind values
1 term1      1
2 term2      1
3 term3      4

$element2
     ind values
1 term23      9
2  term1      2

答案 1 :(得分:3)

我们可以遍历listunlist并使用其中一个按操作分组

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

答案 2 :(得分:3)

试试这个:

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

输出:

$element1
$element1$term1
[1] 1

$element1$term2
[1] 1

$element1$term3
[1] 4


$element2
$element2$term1
[1] 2

$element2$term23
[1] 9

希望这有帮助!

答案 3 :(得分:2)

另一个带有sapply的双循环选项,我们在每个列表中找到匹配的名称,并sum找到它们的值。

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 

如果您想将它们保留为列表列表。请改用lapply

答案 4 :(得分:1)

purrr::map_df可以轻松地将此列表简化为整齐的数据框架,这对于聚合来说是微不足道的:

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