1

My goal is to create a new variable that matches the output from fun(5) for each row but right now fun(1:5) does not give the desired output. Please advise me on how to create a new function that allows me to perform this operation in a vectorized manner since looping it would take a very long time.

I would like f(1:5) to produce a vector of 5 elements, each one matching the output given from f(5) corresponding to each row.

Thanks

names1 = c("x","y","z")
names2 <- c("hi","hello","bye")
fun <- function(x){paste(names2[which(df[x,names1] == 1)],collapse = " ")}
df <- data.frame(a = c(0,1,2,3,4),x = c(0,0,1,0,1),y = c(0,1,0,0,1),z = c(0,1,0,1,0))
fun(5) = "hi hello"
fun(1:5) = "bye NA NA NA NA NA"
Khashaa
  • 7,293
  • 2
  • 21
  • 37
Stephen
  • 324
  • 2
  • 9
  • 2
    It is not clear what do you want? f(1:5) should return what? – cryptomanic Oct 29 '16 at 05:17
  • 2
    Try `sapply(c(1:5), fun)` – Zach Oct 29 '16 at 05:19
  • you can use sapply(1:5, fun) to get a vector [1] "" "hello bye" "hi" "bye" "hi hello" – cryptomanic Oct 29 '16 at 05:21
  • 1
    You could change your `df` to `Map(function(nm1, nm2) ifelse(as.logical(nm1), nm2, ""), df[-1], names2)` and, then, use the `do.call(paste, ...)` approach. `trimws` + `gsub("[[:space:]]+", " ", ...)` or a more sophisticated regex can, then, format the output correctly. This has the advantage of `ncol` looping instead of `nrow` and of using `paste` in a "vectorized" manner. – alexis_laz Oct 29 '16 at 09:39

1 Answers1

2

You could use Vectorize in the following way below (if I understand correctly what the desired result is):

names1 = c("x","y","z")
names2 <- c("hi","hello","bye")
fun <- function(x){
           paste(names2[which(df[x,names1] == 1)],collapse = " ")
}
df <- data.frame(a = c(0,1,2,3,4),
                 x = c(0,0,1,0,1),
                 y = c(0,1,0,0,1),
                 z = c(0,1,0,1,0))
vfun <- Vectorize(fun)
vfun(5)
## [1] "hi hello"
vfun(1:5)
## [1] ""          "hello bye" "hi"        "bye"       "hi hello" 

This essentially puts a wrapper around your function to deal with a vector of values of length > 1.

steveb
  • 5,382
  • 2
  • 27
  • 36
  • This is still a loop. But I'm not optimistic that this can be done without looping. – Roland Oct 29 '16 at 07:53
  • @Roland The above answer vectorizes the code as requested, but for speed optimization, that is a different story as you know. I wasn't sure how important speed optimization really is based on the OP. – steveb Nov 02 '16 at 00:25
  • Vectorize is a wrapper for mapply. See this for a discussion if this should be considered "vectorized": http://stackoverflow.com/q/28983292/1412059 – Roland Nov 02 '16 at 06:01