Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Vectorize `[`

I'm having trouble getting Vectorize to work with [, getting the error shown below. From the help("[") it seems like [ has arguments named x, i, and j - but they don't seem to work when I used them as vectorize.args. Can I do this?

## Some data
dat <- data.frame(a=1:10, b=11:20, c=21:30)

## Vectorize with mapply, seems to work
f <- function(i, j, dat) list(dat[i, j])
mapply(f, list(1:2, 3:4), list(1:2, 2:3), MoreArgs = list(dat=dat))
# [[1]]
#   a  b
# 1 1 11
# 2 2 12
# 
# [[2]]
#    b  c
# 3 13 23
# 4 14 24

## Now using Vectorize, apply to data
Vectorize(`[`, c("i", "j"))(x=dat, i=list(1:2, 2:3), j=list(1:2, 2:3))

Error in Vectorize([, c("i", "j")) : must specify names of formal arguments for 'vectorize'

But, this works (with a warning for naming the arguments)

`[`(x=dat, i=1:2, j=1:2)

Also, if I do this, it's ok

Vectorize(`[.data.frame`, c("i", "j"))(dat, list(1:2, 2:3), list(1:2, 2:3))
like image 493
Rorschach Avatar asked Dec 24 '22 16:12

Rorschach


1 Answers

Vectorize() is documented to not be usable with primitive functions. From ?Vectorize

 ‘Vectorize’ cannot be used with primitive functions as they do not
 have a value for ‘formals’.

And [ is a primitive in R:

> `[`
.Primitive("[")

As [ is already vectorized I don't see the point of even trying this. The usual idiom for your `[`(x=dat, i=1:2, j=1:2) is simply:

dat[1:2, 1:2]

> dat[1:2, 1:2]
  a  b
1 1 11
2 2 12

This indices can be (pre-existing) objects too:

i <- 1:2
j <- 1:2
dat[i, j]

> dat[i, j]
  a  b
1 1 11
2 2 12

If you have more than one set of extractions, then I suppose you could call the [.data.frame method directly in Vectorise. The examples for ?Vectorize illustrate doing this sort of thing for function rep(), which is primitive, so uses rep.int() instead.

like image 154
Gavin Simpson Avatar answered Dec 27 '22 05:12

Gavin Simpson