What Does as.factor() Do in R?
as.factor(x) converts a vector into a factor, R's type for categorical data, with one level for each distinct value in sorted order. Internally a factor is an integer vector of codes plus a character vector of level names. as.factor takes no arguments other than the vector: it cannot set the level order, rename levels, or mark the factor as ordered. For any of those use factor(). If x is already a factor, as.factor returns it unchanged.
Example With Output
colors <- c("red", "blue", "green", "blue", "red") f <- as.factor(colors) f # [1] red blue green blue red # Levels: blue green red levels(f) # [1] "blue" "green" "red" as.integer(f) # [1] 3 1 2 1 3 table(f) # f # blue green red # 2 1 2 str(f) # Factor w/ 3 levels "blue","green",..: 3 1 2 1 3
Three things to read from this output. The levels are the distinct values sorted alphabetically, not in order of first appearance. Each element is stored as the integer position of its level, so "red" is 3. And table counts by level, which is the main reason to convert before summarizing.
For a numeric vector the levels are sorted numerically, so as.factor(c(10, 2, 33)) has levels 2, 10, 33. For a character vector holding numbers the sort is alphabetical, so as.factor(c("10", "2", "33")) has levels 10, 2, 33.
as.factor vs factor
as.factor(x) | factor(x, levels, labels, ordered) | |
|---|---|---|
| Level order | Sorted values, always | Any order you give in levels |
| Rename levels | No | Yes, with labels |
| Ordered factor | No | Yes, with ordered = TRUE |
| Drop or add levels | No | Yes, by listing them in levels |
| Already a factor | Returned unchanged | Rebuilt, dropping unused levels |
| Speed | Faster on large vectors | Slightly slower |
Use as.factor when the default sorted levels are fine and you only need R to treat the column as categorical. Use factor when the order matters. That is the case for any variable with a natural order, and for any plot or model where you want a specific reference level.
size <- c("low", "high", "medium", "low") as.factor(size) # Levels: high low medium (alphabetical, wrong for this data) factor(size, levels = c("low", "medium", "high"), ordered = TRUE) # Levels: low < medium < high (ordered factor)
An ordered factor prints its levels with < and allows comparisons such as x < "high". Modeling functions also treat ordered factors differently, using polynomial contrasts instead of treatment contrasts.
as.factor on a Data Frame Column
The common case is a data frame column read in as character or integer that should be categorical. Assign the result back to the column.
df <- data.frame(id = 1:4, group = c("b", "a", "b", "c"), dose = c(1, 2, 1, 2)) df$group <- as.factor(df$group) # or several columns at once df[c("group", "dose")] <- lapply(df[c("group", "dose")], as.factor) str(df)
Since R 4.0, read.csv and data.frame keep strings as character by default, so this conversion is an explicit step. Models such as lm(y ~ group, data = df) depend on it. A numeric dose of 1 and 2 is fitted as a slope, while a factor dose is fitted as two groups.
The as.numeric Trap
as.numeric on a factor returns the integer codes, not the original numbers. This is the most common factor bug in R.
f <- as.factor(c(10, 20, 10, 30)) as.numeric(f) # [1] 1 2 1 3 (level positions, not the values) as.numeric(as.character(f)) # [1] 10 20 10 30 (correct) as.numeric(levels(f))[f] # [1] 10 20 10 30 (correct and faster on long vectors)
Convert through as.character or index the levels. The same applies when a column that should be numeric became a factor by accident because one cell held text such as "missing".
Renaming and Reordering Levels
levels(f) <- c(...) renames levels by position, so the new names must be given in the current level order. Renaming c("blue", "green", "red") to c("Green", "Red", "Blue") would silently mislabel every value. Two options are safer. factor(f, levels = ..., labels = ...) renames by matching. relevel(f, ref = "red") makes one level the first without changing the data.
Key Takeaways
as.factor(x)builds a factor with levels equal to the sorted distinct values and stores each element as an integer code.- Use
factor()instead when you need a chosen level order, custom labels, or an ordered factor. as.numeric(f)returns codes; useas.numeric(as.character(f))to get the original numbers.- Rename levels by matching, not by position, to avoid silent mislabeling.
- If R is your interview language for a data role, the algorithm rounds still follow the standard patterns. See Grokking the Coding Interview.
- The vectors, hash maps and trees behind those patterns are taught in Grokking Data Structures for Coding Interviews.
- A timed mock interview shows whether you can explain a solution while writing it.

GET YOUR FREE
Coding Questions Catalog

$99

$197

$72