One of the basic data types in R is factors. In my experience factors are basically a pain and I never use them. I always convert to characters. I feel oddly like I'm missing something.
Are there some important examples of functions that use factors as grouping variables where the factor data type becomes necessary? Are there specific circumstances when I should be using factors?
You should use factors. Yes they can be a pain, but my theory is that 90% of why they're a pain is because in
read.table
andread.csv
, the argumentstringsAsFactors = TRUE
by default (and most users miss this subtlety). I say they are useful because model fitting packages like lme4 use factors and ordered factors to differentially fit models and determine the type of contrasts to use. And graphing packages also use them to group by.ggplot
and most model fitting functions coerce character vectors to factors, so the result is the same. However, you end up with warnings in your code:One tricky thing is the whole
drop=TRUE
bit. In vectors this works well to remove levels of factors that aren't in the data. For example:However, with
data.frame
s, the behavior of[.data.frame()
is different: see this email or?"[.data.frame"
. Usingdrop=TRUE
ondata.frame
s does not work as you'd imagine:Luckily you can drop factors easily with
droplevels()
to drop unused factor levels for an individual factor or for every factor in adata.frame
(since R 2.12):This is how to keep levels you've selected out from getting in
ggplot
legends.Internally,
factor
s are integers with an attribute level character vector (seeattributes(iris$Species)
andclass(attributes(iris$Species)$levels)
), which is clean. If you had to change a level name (and you were using character strings), this would be a much less efficient operation. And I change level names a lot, especially forggplot
legends. If you fake factors with character vectors, there's the risk that you'll change just one element, and accidentally create a separate new level.tapply (and aggregate) rely on factors. The information-to-effort ratio of these functions is very high.
For instance, in a single line of code (the call to tapply below) you can get mean price of diamonds by Cut and Color:
Factors are an excellent "unique-cases" badging engine. I've recreated this badly many times, and despite a couple of wrinkles occasionally, they are extremely powerful.
If there's a better way to do this task I'd love to see it, I don't see this capability of
factor
discussed.A
factor
is most analogous to an enumerated type in other languages. Its appropriate use is for a variable which can only take on one of prescribed set of values. In these cases, not every possible allowed value may be present in any particular set of data and the "empty" levels accurately reflect that.Consider some examples. For some data which was collected all across the United States, the state should be recorded as a factor. In this case, the fact that no cases were collected from a particular state is relevant. There could have been data from that state, but there happened (for whatever reason, which may be a reason of interest) to not be. If hometown was collected, it would not be a factor. There is not a pre-stated set of possible hometowns. If data were collected from three towns rather than nationally, the town would be a factor: there are three choices that were given at the outset and if no relevant cases/data were found in one of those three towns, that is relevant.
Other aspects of
factor
s, such as providing a way to give an arbitrary sort order to a set of strings, are useful secondary characteristics offactor
s, but are not the reason for their existence.ordered factors are awesome, if I happen to love oranges and hate apples but don't mind grapes I don't need to manage some weird index to say so:
What a snarky title!
I believe many estimation functions allow you to use factors to easily define dummy variables... but I don't use them for that.
I use them when I have very large character vectors with few unique observations. This can cut down on memory consumption, especially if the strings in the character vector are longer-ish.
PS - I'm joking about the title. I saw your tweet. ;-)