Jacek Kotowski
Jacek Kotowski

Reputation: 704

Sum each list of numerical values within a list

I would like to attach values to labels in a riverplot in R

I have a list of lists of values, which is required to show flows between nodes, like this:

edges <- list( A= list( C= 10, E= 5 ), 
               B= list( C= 10 ), 
               C=list(D = 13, E = 7 )) 

I am aware of a function that would reduce (or sum) one element of a list like this: Reduce("+",edges$A)

Is there a way of reducing such a list of lists of values to a dataframe or so that I could get the sums:

Node Sum
A 15
B 10
C 20
D 13
E 12 

Edit:

I just realised there is a confusion: It looks like I need two outputs and it may be a little more complicated: 1. if 'edges' list has a sublist with a category name, sum up 2. if not, get the sum of all occurences of this item

Case 1: Categories A, B, C (these are the starting nodes) Case 2: Categories D, E (these are the end nodes in a riverplot)

I am sorry for the confusion.

Upvotes: 3

Views: 1771

Answers (4)

989
989

Reputation: 12937

Or using your own proposed Reduce function:

unlist(lapply(edges, function(a) Reduce(sum, a)))

# A  B  C 
#15 10 20 

Upvotes: 1

akrun
akrun

Reputation: 887148

We can also use base R

 v1 <- unlist(edges)
 tapply(v1, sub("\\..*", "", names(v1)), sum)
 # A  B  C 
 #15 10 20 

Or in a single step

 r1 <- tapply(unlist(edges), rep(names(edges), lengths(edges)), FUN = sum)
 r1
 # A  B  C 
 #15 10 20 

if we need to sum based on the names after the .

 r2 <- tapply(v1, sub("[^.]+\\.", "", names(v1)), FUN = sum)
 r2
 # C  D  E 
 #20 13 12 

 c(r1, r2)[!duplicated(c(names(r1), names(r2)))]
 # A  B  C  D  E 
 #15 10 20 13 12 

Or using aggregate/stack

aggregate(values~., stack(edges), FUN = sum)
#    ind values
#1   A     15
#2   B     10
#3   C     20

Upvotes: 3

akuiper
akuiper

Reputation: 214957

Another option is to use purrr package:

library(purrr)
stack(map(edges, compose(sum, unlist)))
#   values ind
# 1     15   A
# 2     10   B
# 3     20   C 

where compose(sum, unlist) is equivalent to function(x) sum(unlist(x)).

Upvotes: 1

Zheyuan Li
Zheyuan Li

Reputation: 73315

I think you can do

lapply(edges, function (x) sum(unlist(x)))

This returns a list. Using sapply will simplify the result to a vector.

Upvotes: 5

Related Questions