Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a `functools.reduce` implementation that looks similarly as `Reduce` in R?

Here is an R example of using Reduce

x <- c(1, 2, 2, 4, 10, 5, 5, 7)
Reduce(\(a, b) if (tail(a, 1) != b) c(a, b) else a, x) # equivalent to `rle(x)$values`

The code above is to sort out the extract unique values in terms of run length, which can be easily obtained by rle(x)$values.


I know in Python there is itertools.groupby that performs the same thing as rle in R, BUT, what I am curious about is: Is it possible to have a highly similar translation by using functools.reduce in Python to achieve the same functionality, say, for example

from functools import reduce
x = [1,2,2,4,10,5,5,7]
reduce(lambda a, b: a + [b] if a[-1]!= b else a, x)

but which unfortunately gives errors like

{
    "name": "TypeError",
    "message": "'int' object is not subscriptable",
    "stack": "---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[58], line 4
      1 from functools import reduce
      2 x = [1,2,2,4,10,5,5,7]
----> 4 reduce(lambda a, b: a + [b] if a[-1]!= b else a, x)

Cell In[58], line 4, in <lambda>(a, b)
      1 from functools import reduce
      2 x = [1,2,2,4,10,5,5,7]
----> 4 reduce(lambda a, b: a + [b] if a[-1]!= b else a, x)

TypeError: 'int' object is not subscriptable"
}

My question is: Is there any one-liner of reduce in Python that looks like R code?

like image 913
ThomasIsCoding Avatar asked Dec 08 '25 08:12

ThomasIsCoding


2 Answers

you could use a list as the initial:

from functools import reduce
x = [1,2,2,4,10,5,5,7]

reduce(lambda a, b: a + [b] if a[-1]!= b else a, x, [x[0]])
[1, 2, 4, 10, 5, 7]

Note that you could use groupby from itertools:


from itertools import groupby
[i for i,j in groupby(x)]
[1, 2, 4, 10, 5, 7]
like image 112
KU99 Avatar answered Dec 09 '25 20:12

KU99


Here is another solution just to highlight the difference. In R a scalar is also a vector of length 1 so tail() or c() has no issues while Python has no concept of scalar[-1] or scalar + list.

def foo(a,b):
  if (isinstance(a, int)): return [a]
  elif a[-1] != b:         return a + [b]
  else:                    return a

reduce(foo, x) 
[1, 2, 4, 10, 5, 7]
like image 28
sindri_baldur Avatar answered Dec 09 '25 21:12

sindri_baldur



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!