How to avoid implicit character conversion when using apply on dataframe
apply, dataframe, r
Solution
Let's wrap up multiple comments into an explanation.
- the use of `apply` converts a `data.frame` to a `matrix`. This means that the least restrictive class will be used. The least restrictive in this case is character.
- You're supplying `1` to `apply`'s `MARGIN` argument. This applies by row and makes you even worse off as you're really mixing classes together now. In this scenario you're using `apply` designed for matrices and data.frames on a vector. This is not the right tool for the job.
- In ths case I'd use `lapply` or `sapply` as rmk points out to grab the classes of the single t2 column as seen below:
Code:
df <- data.frame(v=1:10, t=1:10)
df <- transform(df, t2 = as.POSIXlt(t, origin = "2013-08-13"))
sapply(df[, "t2"], class)
lapply(df[, "t2"], class)
## [[1]]
## [1] "POSIXct" "POSIXt"
##
## [[2]]
## [1] "POSIXct" "POSIXt"
##
## [[3]]
## [1] "POSIXct" "POSIXt"
##
## .
## .
## .
##
## [[9]]
## [1] "POSIXct" "POSIXt"
##
## [[10]]
## [1] "POSIXct" "POSIXt"
In general you choose the `apply` family that fits the job. Often I personally use `lapply` or a `for` loop to act on specific columns or subset the columns I want using indexing (`[, ]`) and then proceed with `apply`. The answer to this problem really boils down to determining what you want to accomplish, asking is `apply` the most appropriate tool, and proceed from there.
May I offer this blog post as an excellent tutorial on what the different `apply` family of functions do.
Problem
When using `apply` on a data.frame, the arguments are (implicitly) converted to character. An example: ``` df <- data.frame(v=1:10, t=1:10) df <- transform(df, t2 = as.POSIXlt(t, origin = "2013-08-13")) class(df$t2[1]) ## [1] "POSIXct" "POSIXt" (correct) ``` but: ``` apply(df, 1, function(y) class(y["t2"])) ## [1] "character" "character" "character" "character" "character" "character" ## [7] "character" "character" "character" "character" ``` Is there any way to avoid this conversion? Or do I always have to convert back through `as.POSIXlt(y["t2"])`? edit My df has 2 timestamps (say, t2 and t3) and some other fields (say, v1, v2). For each row with given t2, I want to find k (e.g. 3) rows with t3 closest to, but lower than t2 (and the same v1), and return a statistics over v2 from these rows (e.g. an average). I wrote a function f(t2, v1, df) and just wanted to apply it on all rows using `apply(df, 1, function(x) f(y["t2"], y["v1"], df)`. Is there any better way to do such things in R?