Julien Laugel
2006-Jul-06 12:30 UTC
[R] use of apply in a data frame on a row by row basis
Hello all, I'm trying to use the apply function on a data frame, by applying a function that takes a one row data.frame as argument . Here's the example : myfun = function(x) paste(x$f1 , x$f2) df = data.frame(f1 = c(1,4,10),f2 = "hello") apply(df,1,myfun) ==> Does not work (I get "character(0)" ) Though : myfun(df[1,]) works, and myfun(df) works as well. So if myfun(df) works, that's fine! BUT, if the output of the function a bit more complex, it does not work : In this case I'm using a timeSeries object (from Rmetrics) library(fMultivar) timerange = timeSequence(from = "2001-04-11", length.out = 3,by = "weeks", format = "%Y-%m-%d", FinCenter = "GMT") myfun2 = function(x) timeSeries(rnorm(3),timerange) In this case, myfun2(df) returns only the result of the 1st row! BUT apply(df,1,myfun2) in this case, does work But I haven't used the "$" notation to access one field Now if I try (and that is the cas that bugs me currently) : myfun3 = function(x) timeSeries(rep(x$f1,3),timerange) myfun3(df) Error in "rownames<-"(`*tmp*`, value = c("2001-04-11 02:00:00", "2001-04-18 02:00:00", : length of 'dimnames' [1] is not equal to range of the array (sorry for the translation : I'm using a french version of R) Though> myfun3(df[1,])TS.1 2001-04-11 02:00:00 1 2001-04-18 02:00:00 1 2001-04-25 02:00:00 1 works well BUT : apply(df,1,myfun3) yields : Error in array(x, c(length(x), 1), if (!is.null(names(x))) list(names(x), : trying to change an attribute in NULL So as a result I'm verry annoyed, and I don't see the logic behind. How can I do to make a apply-like function on the latter function? (myfun3) Many thanks in advance Regards, Roolio [[alternative HTML version deleted]]
Gabor Grothendieck
2006-Jul-06 12:54 UTC
[R] use of apply in a data frame on a row by row basis
On 7/6/06, Julien Laugel <roolio4news at gmail.com> wrote:> Hello all, > > I'm trying to use the apply function on a data frame, > by applying a function that takes a one row data.frame as argument . > > Here's the example : > myfun = function(x) paste(x$f1 , x$f2) > df = data.frame(f1 = c(1,4,10),f2 = "hello") > > apply(df,1,myfun) ==> Does not work (I get "character(0)" )Try one of these: sapply(split(df, rownames(df)), myfun) sapply(1:nrow(df), function(i) paste(df$f1[i], df$f2[i])) sapply(1:nrow(df), function(i) paste(df[i,1], df[i,2]))> > Though : myfun(df[1,]) works, > and myfun(df) works as well. > > So if myfun(df) works, that's fine! > BUT, if the output of the function a bit more complex, it does not work : > In this case I'm using a timeSeries object (from Rmetrics) > > library(fMultivar) > timerange = timeSequence(from = "2001-04-11", length.out = 3,by = "weeks", > format = "%Y-%m-%d", FinCenter = "GMT") > myfun2 = function(x) timeSeries(rnorm(3),timerange) > > In this case, myfun2(df) returns only the result of the 1st row! > BUT > apply(df,1,myfun2) in this case, does work > > But I haven't used the "$" notation to access one field > Now if I try (and that is the cas that bugs me currently) : > > myfun3 = function(x) timeSeries(rep(x$f1,3),timerange) > > myfun3(df) > Error in "rownames<-"(`*tmp*`, value = c("2001-04-11 02:00:00", "2001-04-18 > 02:00:00", : > length of 'dimnames' [1] is not equal to range of the array > (sorry for the translation : I'm using a french version of R) > Though > > myfun3(df[1,]) > TS.1 > 2001-04-11 02:00:00 1 > 2001-04-18 02:00:00 1 > 2001-04-25 02:00:00 1 > works well > BUT : > apply(df,1,myfun3) > yields : > > Error in array(x, c(length(x), 1), if (!is.null(names(x))) list(names(x), : > trying to change an attribute in NULL > > So as a result I'm verry annoyed, and I don't see the logic behind. > How can I do to make a apply-like function on the latter function? (myfun3) > > Many thanks in advance > > Regards, > > Roolio > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html >
?apply has the answer, in particular, in the "Detail" section: If X is not an array but has a dimension attribute, apply attempts to coerce it to an array via as.matrix if it is two-dimensional (e.g., data frames) or via as.array. Thus the function being apply()'ed should not be expecting a 1-row data frame. Instead, it should be expecting a vector. Andy From: Julien Laugel> > Hello all, > > I'm trying to use the apply function on a data frame, by > applying a function that takes a one row data.frame as argument . > > Here's the example : > myfun = function(x) paste(x$f1 , x$f2) > df = data.frame(f1 = c(1,4,10),f2 = "hello") > > apply(df,1,myfun) ==> Does not work (I get "character(0)" ) > > Though : myfun(df[1,]) works, > and myfun(df) works as well. > > So if myfun(df) works, that's fine! > BUT, if the output of the function a bit more complex, it > does not work : > In this case I'm using a timeSeries object (from Rmetrics) > > library(fMultivar) > timerange = timeSequence(from = "2001-04-11", length.out = > 3,by = "weeks", format = "%Y-%m-%d", FinCenter = "GMT") > myfun2 = function(x) timeSeries(rnorm(3),timerange) > > In this case, myfun2(df) returns only the result of the 1st row! > BUT > apply(df,1,myfun2) in this case, does work > > But I haven't used the "$" notation to access one field Now > if I try (and that is the cas that bugs me currently) : > > myfun3 = function(x) timeSeries(rep(x$f1,3),timerange) > > myfun3(df) > Error in "rownames<-"(`*tmp*`, value = c("2001-04-11 > 02:00:00", "2001-04-18 02:00:00", : > length of 'dimnames' [1] is not equal to range of the array > (sorry for the translation : I'm using a french version of R) Though > > myfun3(df[1,]) > TS.1 > 2001-04-11 02:00:00 1 > 2001-04-18 02:00:00 1 > 2001-04-25 02:00:00 1 > works well > BUT : > apply(df,1,myfun3) > yields : > > Error in array(x, c(length(x), 1), if (!is.null(names(x))) > list(names(x), : > trying to change an attribute in NULL > > So as a result I'm verry annoyed, and I don't see the logic behind. > How can I do to make a apply-like function on the latter > function? (myfun3) > > Many thanks in advance > > Regards, > > Roolio > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help at stat.math.ethz.ch mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide! > http://www.R-project.org/posting-guide.html > >