Question: A very unexpected behavior of the useful `data.frame` in R arises from keeping `character` columns as factor. This causes many problems if it is not considered. For example suppose the following code:

```
foo=data.frame(name=c("c","a"),value=1:2)
#   name val
# 1    c   1
# 2    a   2

bar=matrix(1:6,nrow=3)
rownames(bar)=c("a","b","c")
#   [,1] [,2]
# a    1    4
# b    2    5
# c    3    6

```

Then what do you expect of running `bar[foo$name,]`? It normally should return the rows of `bar` that are named according to the `foo$name` that means rows 'c' and 'a'. But the result is different:

```
bar[foo$name,]
#   [,1] [,2]
# b    2    5
# a    1    4

```

The reason is here: `foo$name` is not a character vector, but an integer vector.

```
foo$name
# [1] c a
# Levels: a c

```

To have the expected behavior, I manually convert it to character vector:

```
foo$name = as.character(foo$name)
bar[foo$name,]
#   [,1] [,2]
# c    3    6
# a    1    4

```

But the problem is that we may easily miss to perform this, and have hidden bugs in our codes. Is there any better solution?

Answer: 
This is a feature and R is working as documented. This can be dealt with generally in a few ways:

1. use the argument `stringsAsFactors = TRUE` in the call to `data.frame()`. See `?data.frame`
2. if you detest this behaviour so, set the option globally via

```
options(stringsAsFactors = FALSE)

```
3. (as noted by @JoshuaUlrich in comments) a third option is to wrap character variables in `I(....)`. This alters the class of the object being assigned to the data frame component to include `"AsIs"`. In general this shouldn't be a problem as the object inherits (in this case) the class `"character"` so should work as before.

You can check what the default for `stringsAsFactors` is on the currently running R process via:

```
> default.stringsAsFactors()
[1] TRUE

```

The issue is slightly wider than `data.frame()` in scope as this also affects `read.table()`. In that function, as well as the two options above, you can also tell R what all the classes of the variables are via argument `colClasses` and R will respect that, e.g.

```
> tmp <- read.table(text = '"Var1","Var2"
+ "A","B"
+ "C","C"
+ "B","D"', header = TRUE, colClasses = rep("character", 2), sep = ",")
> str(tmp)
'data.frame':   3 obs. of  2 variables:
 $ Var1: chr  "A" "C" "B"
 $ Var2: chr  "B" "C" "D"

```
In the example data below, author and title are automatically converted to factor (unless you add the argument `stringsAsFactors = FALSE` when you are creating the data). What if we forgot to change the default setting and don't want to set the options globally?

Some code I found somewhere (most likely SO) uses `sapply()` to identify factors and convert them to strings.

```
dat = data.frame(title = c("title1", "title2", "title3"),
                 author = c("author1", "author2", "author3"),
                 customerID = c(1, 2, 1))
# > str(dat)
# 'data.frame': 3 obs. of  3 variables:
#   $ title     : Factor w/ 3 levels "title1","title2",..: 1 2 3
#   $ author    : Factor w/ 3 levels "author1","author2",..: 1 2 3
#   $ customerID: num  1 2 1

dat[sapply(dat, is.factor)] = lapply(dat[sapply(dat, is.factor)], 
                                 as.character)
# > str(dat)
# 'data.frame':  3 obs. of  3 variables:
#   $ title     : chr  "title1" "title2" "title3"
#   $ author    : chr  "author1" "author2" "author3"
#   $ customerID: num  1 2 1

```

I *assume* this would be faster than re-reading in the dataset with the `stringsAsFactors = FALSE` argument, but have never tested.