[R] Reduce woes

jeremiah rounds roundsjeremiah at gmail.com
Thu Jul 28 21:19:32 CEST 2016


Basically using Reduce as an lapply in that example, but I think that was
caused by how people started talking about things in the first place =) But
the point is the accumulator can be anything as far as I can tell.

On Thu, Jul 28, 2016 at 12:14 PM, jeremiah rounds <roundsjeremiah at gmail.com>
wrote:

> Re:
> "What I'm trying to
> work out is how to have the accumulator in Reduce not be the same type as
> the elements of the vector/list being reduced - ideally it could be an S3
> instance, list, vector, or data frame."
>
> Pretty sure that is not true.  See code that follows.  I would never solve
> this task in this way though so no comment on the use of Reduce for what
> you described.  (Note the accumulation of "functions" in a list is just a
> demo of possibilities).  You could accumulate in an environment too and
> potentially gain a lot of copy efficiency.
>
>
> lookup = list()
> lookup[[as.character(1)]] = function() print("1")
> lookup[[as.character(2)]] = function() print("2")
> lookup[[as.character(3)]] = function() print("3")
>
> data = list(c(1,2), c(1,4), c(3,3), c(2,30))
>
>
> r = Reduce(function(acc, item) {
> append(acc, list(lookup[[as.character(min(item))]]))
> }, data,list())
> r
> for(f in r) f()
>
>
> On Thu, Jul 28, 2016 at 5:09 AM, Stefan Kruger <stefan.kruger at gmail.com>
> wrote:
>
>> Ulrik - many thanks for your reply.
>>
>> I'm aware of many simple solutions as the one you suggest, both iterative
>> and functional style - but I'm trying to learn how to bend Reduce() for
>> the
>> purpose of using it in more complex processing tasks. What I'm trying to
>> work out is how to have the accumulator in Reduce not be the same type as
>> the elements of the vector/list being reduced - ideally it could be an S3
>> instance, list, vector, or data frame.
>>
>> Here's a more realistic example (in Elixir, sorry)
>>
>> Given two lists:
>>
>> 1. data: maps an id string to a vector of revision strings
>> 2. dict: maps known id/revision pairs as a string to true (or 1)
>>
>> find the items in data not already in dict, returned as a named list.
>>
>> ```elixir
>> data = %{
>>     "id1" => ["rev1.1", "rev1.2"],
>>     "id2" => ["rev2.1"],
>>     "id3" => ["rev3.1", "rev3.2", "rev3.3"]
>> }
>>
>> dict = %{
>>     "id1/rev1.1" => 1,
>>     "id1/rev1.2" => 1,
>>     "id3/rev3.1" => 1
>> }
>>
>> # Find the items in data not already in dict. Return as a grouped map
>>
>> Map.keys(data)
>>     |> Enum.flat_map(fn id -> Enum.map(data[id], fn rev -> {id, rev} end)
>> end)
>>     |> Enum.filter(fn {id, rev} -> !Dict.has_key?(dict, "#{id}/#{rev}")
>> end)
>>     |> Enum.reduce(%{}, fn ({k, v}, d) -> Map.update(d, k, [v], &[v|&1])
>> end)
>> ```
>>
>>
>>
>>
>> On 28 July 2016 at 12:03, Ulrik Stervbo <ulrik.stervbo at gmail.com> wrote:
>>
>> > Hi Stefan,
>> >
>> > in that case,lapply(data, length) should do the trick.
>> >
>> > Best wishes,
>> > Ulrik
>> >
>> > On Thu, 28 Jul 2016 at 12:57 Stefan Kruger <stefan.kruger at gmail.com>
>> > wrote:
>> >
>> >> 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]]
>> >>
>> >> ______________________________________________
>> >> 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.
>> >>
>> >
>>
>>
>> --
>> 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.
>>
>
>

	[[alternative HTML version deleted]]



More information about the R-help mailing list