Hi - I'm new to R. In other functional languages I'm familiar with you can often seed a call to reduce() with a custom accumulator. Here's an example in Elixir: map = %{"one" => [1, 1], "three" => [3], "two" => [2, 2]} map |> Enum.reduce(%{}, fn ({k,v}, acc) -> Map.update(acc, k, Enum.count(v), nil) end) # %{"one" => 2, "three" => 1, "two" => 2} In R-terms that's reducing a list of vectors to become a new list mapping the names to the vector lengths. Even in JavaScript, you can do similar things: list = { one: [1, 1], three: [3], two: [2, 2] }; var result = Object.keys(list).reduceRight(function (acc, item) { acc[item] = list[item].length; return acc; }, {}); // result == { two: 2, three: 1, one: 2 } In R, from what I can gather, Reduce() is restricted such that any init value you feed it is required to be of the same type as the elements of the vector you're reducing -- so I can't build up. So whilst I can do, say> Reduce(function(acc, item) { acc + item }, c(1,2,3,4,5), 96)[1] 111 I can't use Reduce to build up a list, vector or data frame? What am I missing? Many thanks for any pointers, Stefan -- Stefan Kruger <stefan.kruger at gmail.com> [[alternative HTML version deleted]]
If you have a simple list of vectors (call it lst), use lengths = sapply(lst, length) In general, you may want to look at functions lapply and sapply which apply a function over a list, in this case the function length(). Peter On Wed, Jul 27, 2016 at 8:20 AM, Stefan Kruger <stefan.kruger at gmail.com> wrote:> Hi - > > I'm new to R. > > In other functional languages I'm familiar with you can often seed a call > to reduce() with a custom accumulator. Here's an example in Elixir: > > map = %{"one" => [1, 1], "three" => [3], "two" => [2, 2]} > map |> Enum.reduce(%{}, fn ({k,v}, acc) -> Map.update(acc, k, > Enum.count(v), nil) end) > # %{"one" => 2, "three" => 1, "two" => 2} > > In R-terms that's reducing a list of vectors to become a new list mapping > the names to the vector lengths. > > Even in JavaScript, you can do similar things: > > list = { one: [1, 1], three: [3], two: [2, 2] }; > var result = Object.keys(list).reduceRight(function (acc, item) { > acc[item] = list[item].length; > return acc; > }, {}); > // result == { two: 2, three: 1, one: 2 } > > In R, from what I can gather, Reduce() is restricted such that any init > value you feed it is required to be of the same type as the elements of the > vector you're reducing -- so I can't build up. So whilst I can do, say > >> Reduce(function(acc, item) { acc + item }, c(1,2,3,4,5), 96) > [1] 111 > > I can't use Reduce to build up a list, vector or data frame? > > What am I missing? > > Many thanks for any pointers, > > Stefan > > > > -- > Stefan Kruger <stefan.kruger at gmail.com> > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.
> On Jul 27, 2016, at 8:20 AM, Stefan Kruger <stefan.kruger at gmail.com> wrote: > > Hi - > > I'm new to R. > > In other functional languages I'm familiar with you can often seed a call > to reduce() with a custom accumulator. Here's an example in Elixir: > > map = %{"one" => [1, 1], "three" => [3], "two" => [2, 2]} > map |> Enum.reduce(%{}, fn ({k,v}, acc) -> Map.update(acc, k, > Enum.count(v), nil) end) > # %{"one" => 2, "three" => 1, "two" => 2} > > In R-terms that's reducing a list of vectors to become a new list mapping > the names to the vector lengths. > > Even in JavaScript, you can do similar things: > > list = { one: [1, 1], three: [3], two: [2, 2] }; > var result = Object.keys(list).reduceRight(function (acc, item) { > acc[item] = list[item].length; > return acc; > }, {}); > // result == { two: 2, three: 1, one: 2 } > > In R, from what I can gather, Reduce() is restricted such that any init > value you feed it is required to be of the same type as the elements of the > vector you're reducing -- so I can't build up. So whilst I can do, say > >> Reduce(function(acc, item) { acc + item }, c(1,2,3,4,5), 96) > [1] 111 > > I can't use Reduce to build up a list, vector or data frame? > > What am I missing? > > Many thanks for any pointers,This builds a list:> Reduce(function(acc, item) { c(acc , item) }, c(1,2,3,4,5), 96, accumulate=TRUE)[[1]] [1] 96 [[2]] [1] 96 1 [[3]] [1] 96 1 2 [[4]] [1] 96 1 2 3 [[5]] [1] 96 1 2 3 4 [[6]] [1] 96 1 2 3 4 5 But you are not saying what you want. The other examples were doing something with names but you provided no names for the R example. This would return a list of named vectors:> Reduce(function(acc, item) { setNames( c(acc,item), 1:(item+1)) }, c(1,2,3,4,5), 96, accumulate=TRUE)[[1]] [1] 96 [[2]] 1 2 96 1 [[3]] 1 2 3 96 1 2 [[4]] 1 2 3 4 96 1 2 3 [[5]] 1 2 3 4 5 96 1 2 3 4 [[6]] 1 2 3 4 5 6 96 1 2 3 4 5> Stefan > > > > -- > Stefan Kruger <stefan.kruger at gmail.com> > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.David Winsemius Alameda, CA, USA
David - many thanks for your response. What I tried to do was to turn data <- list(one = c(1, 1), three = c(3), two = c(2, 2)) into result <- list(one = 2, three = 1, two = 2) that is creating a new list which has the same names as the first, but where the values are the vector lengths. I know there are many other (and better) trivial ways of achieving this - my aim is less the task itself, and more figuring out if this can be done using Reduce() in the fashion I showed in the other examples I gave. It's a building block of doing map-filter-reduce type pipelines that I'd like to understand how to do in R. Fumbling in the dark, I tried: Reduce(function(acc, item) { setNames(c(acc, length(data[item])), item }, names(data), accumulate=TRUE) but setNames sets all the names, not adding one - and acc is still a vector, not a list. It looks like 'lambda.tools.fold()' and possibly 'purrr.reduce()' aim at doing what I'd like to do - but I've not been able to figure out quite how. Thanks Stefan On 27 July 2016 at 20:35, David Winsemius <dwinsemius at comcast.net> wrote:> > > On Jul 27, 2016, at 8:20 AM, Stefan Kruger <stefan.kruger at gmail.com> > wrote: > > > > Hi - > > > > I'm new to R. > > > > In other functional languages I'm familiar with you can often seed a call > > to reduce() with a custom accumulator. Here's an example in Elixir: > > > > map = %{"one" => [1, 1], "three" => [3], "two" => [2, 2]} > > map |> Enum.reduce(%{}, fn ({k,v}, acc) -> Map.update(acc, k, > > Enum.count(v), nil) end) > > # %{"one" => 2, "three" => 1, "two" => 2} > > > > In R-terms that's reducing a list of vectors to become a new list mapping > > the names to the vector lengths. > > > > Even in JavaScript, you can do similar things: > > > > list = { one: [1, 1], three: [3], two: [2, 2] }; > > var result = Object.keys(list).reduceRight(function (acc, item) { > > acc[item] = list[item].length; > > return acc; > > }, {}); > > // result == { two: 2, three: 1, one: 2 } > > > > In R, from what I can gather, Reduce() is restricted such that any init > > value you feed it is required to be of the same type as the elements of > the > > vector you're reducing -- so I can't build up. So whilst I can do, say > > > >> Reduce(function(acc, item) { acc + item }, c(1,2,3,4,5), 96) > > [1] 111 > > > > I can't use Reduce to build up a list, vector or data frame? > > > > What am I missing? > > > > Many thanks for any pointers, > > This builds a list: > > > Reduce(function(acc, item) { c(acc , item) }, c(1,2,3,4,5), 96, > accumulate=TRUE) > [[1]] > [1] 96 > > [[2]] > [1] 96 1 > > [[3]] > [1] 96 1 2 > > [[4]] > [1] 96 1 2 3 > > [[5]] > [1] 96 1 2 3 4 > > [[6]] > [1] 96 1 2 3 4 5 > > But you are not saying what you want. The other examples were doing > something with names but you provided no names for the R example. > > This would return a list of named vectors: > > > Reduce(function(acc, item) { setNames( c(acc,item), 1:(item+1)) }, > c(1,2,3,4,5), 96, accumulate=TRUE) > [[1]] > [1] 96 > > [[2]] > 1 2 > 96 1 > > [[3]] > 1 2 3 > 96 1 2 > > [[4]] > 1 2 3 4 > 96 1 2 3 > > [[5]] > 1 2 3 4 5 > 96 1 2 3 4 > > [[6]] > 1 2 3 4 5 6 > 96 1 2 3 4 5 > > > > > > Stefan > > > > > > > > -- > > Stefan Kruger <stefan.kruger at gmail.com> > > > > [[alternative HTML version deleted]] > > > > ______________________________________________ > > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > > https://stat.ethz.ch/mailman/listinfo/r-help > > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > > and provide commented, minimal, self-contained, reproducible code. > > David Winsemius > Alameda, CA, USA > >-- Stefan Kruger <stefan.kruger at gmail.com> [[alternative HTML version deleted]]