In order to preserve the classes of the defined variables you must do two things:
1) Set stringsAsFactors = FALSE, so the character variable doesnt become a factor.
2) New row must be a list.
Like in this example:
> df.empty <- data.frame(column1 = numeric(), column2 = character(),
+ column3 = factor(levels=c("A","B","C")), stringsAsFactors = FALSE)
>
> newRow <- list(-2, "MyString","B")
> incorrectRow <- list(-2, "MyString", "C")
>
> # Not mess columns names
>
> df.empty[nrow(df.empty) + 1,] <- newRow
> df.empty[nrow(df.empty) + 1,] <- incorrectRow
>
> df.empty
column1 column2 column3
1 -2 MyString B
2 -2 MyString C
> summary(df.empty)
column1 column2 column3
Min. :-2 Length:2 A:0
1st Qu.:-2 Class :character B:1
Median :-2 Mode :character C:1
Mean :-2
3rd Qu.:-2
Max. :-2
For preserving the columns names, the credit goes to this anwser:
https://stackoverflow.com/a/15718454/8382633
My first attemp was also with rbind, but it has some drawbacks. It doesnt preserve columns names, an also, convert all strings to factors, or if you set stringsAsFactors = FALSE, all factors to strings!!
> df.empty <- rbind.data.frame(df.empty, newRow, incorrectRow)
>
> summary(df.empty)
c..2...2. c..MyString....MyString.. c..B....C..
Min. :-2 MyString:2 B:1
1st Qu.:-2 C:1
Median :-2
Mean :-2
3rd Qu.:-2
Max. :-2
> class(df.empty$c..MyString....MyString..)
[1] "factor"
or with stringsAsFactors = FALSE:
> df.empty <- rbind.data.frame(df.empty, newRow, incorrectRow, stringsAsFactors = FALSE)
>
> summary(df.empty)
c..2...2. c..MyString....MyString.. c..B....C..
Min. :-2 Length:2 Length:2
1st Qu.:-2 Class :character Class :character
Median :-2 Mode :character Mode :character
Mean :-2
3rd Qu.:-2
Max. :-2
>
> class(df.empty$c..B....C..)
[1] "character"
I was thinking it was close to a duplicate. But in the end, this questions opened more questions to me.
Hope it helps.