2

I am trying to apply a function that uses multiple columns of a dataframe as arguments, with the function returning a dataframe for each row. I can use a for loop here, but Wanted to check if there is any other way of doing this

A simple example is being provided here. my original problem is slightly more complicated.

DF1<-data.frame(start=seq(from=1, to=5, by=1),end=seq(from=10, to=14, by=1))

rep_fun <- function(x,y)
{
  data.frame( A=seq(x, y)) #produces a sequence between x and y
}

DF2<-data.frame()
for (i in 1:nrow(DF1)){
  temp<-data.frame(rep_fun(DF1$start[i],DF1$end[i]))
 DF2<-rbind(temp,DF2) # this contains a dataframe that has a sequence between 'start' and 'end' for  each row in DF1 

}

The desired result which I am able to obtain through a for-loop is shown below. Not all rows are being shown here. Rows 1 to 10, shows the sequence corresponding to row 5 in DF1

> DF2
    A
1   5
2   6
3   7
4   8
5   9
6  10
7  11
8  12
9  13
10 14
11  4
12  5
2
  • I trust this is a case of the xy problem. But here is a possible approach: as.vector(apply(DF1, 1, function(x) x[1] : x[2])) Commented Nov 4, 2017 at 12:52
  • As I had mentioned, my original problem is more complicated. The rep_fun equivalent in my original problem will return a multi row and multi column data frame. Commented Nov 4, 2017 at 12:57

1 Answer 1

3

1) lapply Split DF1 by nrow(DF1):1 so that it comes out in reverse order and then lapply over that list and rbind its components together. No packages are used.

DF3 <- do.call("rbind", lapply(split(DF1, nrow(DF1):1), with, rep_fun(start, end)))
rownames(DF3) <- NULL

identical(DF2, DF3)
## [1] TRUE

2) Map or this alternative:

fun <- function(x) with(x, rep_fun(start, end))
DF4 <- do.call("rbind", Map(fun, split(DF1, nrow(DF1):1), USE.NAMES = FALSE))

identical(DF4, DF2)
## [1] TRUE

3) Map/rev Like (2) this uses Map but this time using rep_fun directly. Also, it uses rev to order the output after the computation rather than split to order the input before the computation.

DF5 <- do.call("rbind", with(DF1, rev(Map(rep_fun, start, end))))

identical(DF5, DF2)
## [1] TRUE
Sign up to request clarification or add additional context in comments.

1 Comment

The reversing thing wasnt a requirement to be honest, but great to find out that is possible! Option 3 is the one I am going with. Its about 3 times faster than the For loop option in my original problem!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.