Factors in R have two components: their "index" (my term), which is just a vector of integers, and their "level", which is a vector of characters (or integers, though it's most helpful to think of them as just characters for now). Matloff explains this well in his book The Art of R Programming, but I'll give my own quick example here. > f = factor(c(10,11,12,11)) > f [1] 10 11 12 11 Levels: 10 11 12 > levels(f) [1] "10" "11" "12" > unclass(f) [1] 1 2 3 2 attr(,"levels") [1] "10" "11" "12" > attributes(f) $levels [1] "10" "11" "12" $class [1] "factor" You can see that R's internal representation of factors is just as I explained above. That is, there is an integer index that is essentially a lookup table with integer indicies that point to the "labels" character vector. The "labels" character vector attribute is the factor's second component. While perhaps a bit confusing, this is all relatively straightforward. Where factors can get really frustrating, however, is when different functions use different parts of the factor; some use the de-referenced "levels" of the factor, whereas others use the index values. This problem is most evident in the as.character() and as.numeric() functions: > as.character(f) [1] "10" "11" "12" "11" > as.numeric(f) [1] 1 2 3 2 What's happening here? as.character() is dereferencing the index and returning the character levels. On the other hand, as.numeric() is returning the /index vector/ part of the factor. This is probably not what you'd expect if you have numeric factors, such as we have above. When you want to turn your factor into numbers, what you probably want to do is: > as.numeric(as.character(f)) [1] 10 11 12 11 I've been using R for years now, and I finally took the time to look into this and resolve it. I'm sure I'll run into more unexpected behaviors in the future, but I'm glad to have at least solved this aspect of factor behavior in R. Do you have any other examples? Feel free to share them in the comments!
Showing posts with label R. Show all posts
Showing posts with label R. Show all posts
Wednesday, March 20, 2013
resolving factor frustration in R
Wednesday, May 9, 2012
pushd / popd for R
Hi Folks,
I haven't gotten around to putting my R code in nice objects yet. So, my code is procedural, and it's nasty. It sources one script to the next, processing data, analyzing data, etc. As the scripts get run around the codebase, they often change their working directory. So, I wanted access to a bash-equivalent pushd and popd. I'll run these at the beginning and end of each script.
These are not battle-tested yet, and there's really no error-checking or redundancy in them. So, use with care, and they'll probably evolve over time. Feel free to add to them in the comments!
Enjoy!
I haven't gotten around to putting my R code in nice objects yet. So, my code is procedural, and it's nasty. It sources one script to the next, processing data, analyzing data, etc. As the scripts get run around the codebase, they often change their working directory. So, I wanted access to a bash-equivalent pushd and popd. I'll run these at the beginning and end of each script.
These are not battle-tested yet, and there's really no error-checking or redundancy in them. So, use with care, and they'll probably evolve over time. Feel free to add to them in the comments!
Enjoy!
# push getwd() strings into a FIFO vector
dir_fifo = c()
pushd <- function(cd) {
dir_fifo = c()
pushd <- function(cd) {
# usage: pushd("directory to change to")
dir_fifo = append(dir_fifo, getwd(), 0)
assign("dir_fifo", dir_fifo, envir = .GlobalEnv)
setwd(cd)
}
popd <- function() {
dir_fifo = append(dir_fifo, getwd(), 0)
assign("dir_fifo", dir_fifo, envir = .GlobalEnv)
setwd(cd)
}
popd <- function() {
# usage: popd()
setwd(dir_fifo[1])
dir_fifo = dir_fifo[-1]
assign("dir_fifo", dir_fifo, envir = .GlobalEnv)
}
setwd(dir_fifo[1])
dir_fifo = dir_fifo[-1]
assign("dir_fifo", dir_fifo, envir = .GlobalEnv)
}
Subscribe to:
Posts (Atom)