EDIT:
Your code is NOT Wrong.
You just have to reconvert your result into factor like this:
df<-data.frame(B=c("A","B","C","C"), C=c("A","C","B","B"), D=c("B","A","C","A") )
df$A<-levels(df$B)[with(df,ifelse(df$B==df$C,df$D,df$C))]
To see why this happen you have to see what ifelse does:
debugonce(ifelse)
ifelse(df$B==df$C,df$D,df$C)
Keep in Mind "Factor variables are stored, internally, as numeric variables together with their levels. The actual values of the numeric variable are 1, 2, and so on."
In particular ifelse assign to the answer vector boolean values, that is you start with a logical vector. Then based on test comparison, ifelse subset this ans vector assigning "yes" values. So R keep the vector rapresentation.
Briefly something like this happen and you lose the factor rapresentation
a<-c(TRUE,FALSE)
a[1]<-df$D[1]
df$D
a
Try also this working example (an alternative way to do the same thing)
df<-data.frame(B=c("A","B","C","C"), C=c("A","C","B","B"), D=c("B","A","C","A") )
f<-data.frame(b,c,d)
df
f<-function(x,y,z){
if(x==y){
z
}else{
y
}
}
df$A<-unlist(Map(f,df$B,df$C,df$D))