Look at the source of the tolower (you can do this simply by entering the name of the tolower variable in the console or by typing print(tolower) ):
if (!is.character(x)) x <- as.character(x)
Your factor column is forcibly bound to the character vector.
Instead, I believe you want:
levels(df$names) <- tolower(levels(df$names))
It is also more efficient, since we only need to replace the length(levels(df$names)) values ββin memory, as a rule, much less than replacing the full vector of nrow(df) values.
source share