Reputation: 704
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
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
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
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
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