[R] Reduce woes

Stefan Kruger stefan.kruger at gmail.com
Thu Jul 28 14:09:51 CEST 2016


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



More information about the R-help mailing list