Mark Na
2009-Jun-24 16:34 UTC
[R] How to avoid ifelse statement converting factor to character
Hi R-helpers, Please see the below R output. The problem is that after running the ifelse statement, data$SOCIAL_STATUS is converted from a factor to a character. Is there some way I can avoid this conversion? Thanks in advance, Mark Na> str(data)'data.frame': 2100 obs. of 11 variables: $ DATE : Factor w/ 5 levels "4-Jun-09","7-May-09",..: 1 1 1 1 1 1 1 1 1 1 ... $ POND_ID : Factor w/ 113 levels "10","18","19",..: 8 8 8 8 8 8 8 8 8 8 ... $ STATUS : num 1 1 1 1 1 1 1 1 1 1 ... $ SPECIES : Factor w/ 25 levels "AGWT","AMCO",..: 10 10 7 7 3 5 5 5 5 2 ... $ SOCIAL_STATUS : Factor w/ 8 levels "A","B","D","E",..: 4 1 4 1 4 4 4 4 1 6 ... $ COUNT_OF_GROUPS: num 1 1 1 1 1 3 3 3 1 2 ... $ MALE : num 1 1 1 1 1 1 1 1 1 0 ... $ FEMALE : num 1 0 1 0 1 1 1 1 0 0 ... $ NOSEX : num 0 0 0 0 0 0 0 0 0 2 ... $ UPLAND : num 0 0 0 0 0 0 0 0 0 0 ... $ TAG : num 0 0 0 0 0 0 0 0 0 0 ...> data$SOCIAL_STATUS<-ifelse(data$SOCIAL_STATUS=="B" & data$MALE>4, "C",data$SOCIAL_STATUS)> str(data)'data.frame': 2100 obs. of 11 variables: $ DATE : Factor w/ 5 levels "4-Jun-09","7-May-09",..: 1 1 1 1 1 1 1 1 1 1 ... $ POND_ID : Factor w/ 113 levels "10","18","19",..: 8 8 8 8 8 8 8 8 8 8 ... $ STATUS : num 1 1 1 1 1 1 1 1 1 1 ... $ SPECIES : Factor w/ 25 levels "AGWT","AMCO",..: 10 10 7 7 3 5 5 5 5 2 ... $ SOCIAL_STATUS : chr "4" "1" "4" "1" ... $ COUNT_OF_GROUPS: num 1 1 1 1 1 3 3 3 1 2 ... $ MALE : num 1 1 1 1 1 1 1 1 1 0 ... $ FEMALE : num 1 0 1 0 1 1 1 1 0 0 ... $ NOSEX : num 0 0 0 0 0 0 0 0 0 2 ... $ UPLAND : num 0 0 0 0 0 0 0 0 0 0 ... $ TAG : num 0 0 0 0 0 0 0 0 0 0 ... [[alternative HTML version deleted]]
Henrique Dallazuanna
2009-Jun-24 16:47 UTC
[R] How to avoid ifelse statement converting factor to character
You can work with levels of factor: levels(DF$SOCIAL_STATUS)[DF$MALE > 4 & DF$SOCIAL_STATUS == "B"] <- "C" On Wed, Jun 24, 2009 at 1:34 PM, Mark Na <mtb954@gmail.com> wrote:> Hi R-helpers, > > Please see the below R output. > The problem is that after running the ifelse statement, data$SOCIAL_STATUS > is converted from a factor to a character. > > Is there some way I can avoid this conversion? > > Thanks in advance, Mark Na > > > > str(data) > 'data.frame': 2100 obs. of 11 variables: > $ DATE : Factor w/ 5 levels "4-Jun-09","7-May-09",..: 1 1 1 1 1 1 > 1 1 1 1 ... > $ POND_ID : Factor w/ 113 levels "10","18","19",..: 8 8 8 8 8 8 8 8 > 8 > 8 ... > $ STATUS : num 1 1 1 1 1 1 1 1 1 1 ... > $ SPECIES : Factor w/ 25 levels "AGWT","AMCO",..: 10 10 7 7 3 5 5 5 > 5 > 2 ... > $ SOCIAL_STATUS : Factor w/ 8 levels "A","B","D","E",..: 4 1 4 1 4 4 4 4 1 > 6 ... > $ COUNT_OF_GROUPS: num 1 1 1 1 1 3 3 3 1 2 ... > $ MALE : num 1 1 1 1 1 1 1 1 1 0 ... > $ FEMALE : num 1 0 1 0 1 1 1 1 0 0 ... > $ NOSEX : num 0 0 0 0 0 0 0 0 0 2 ... > $ UPLAND : num 0 0 0 0 0 0 0 0 0 0 ... > $ TAG : num 0 0 0 0 0 0 0 0 0 0 ... > > > data$SOCIAL_STATUS<-ifelse(data$SOCIAL_STATUS=="B" & data$MALE>4, "C", > data$SOCIAL_STATUS) > > > str(data) > 'data.frame': 2100 obs. of 11 variables: > $ DATE : Factor w/ 5 levels "4-Jun-09","7-May-09",..: 1 1 1 1 1 1 > 1 1 1 1 ... > $ POND_ID : Factor w/ 113 levels "10","18","19",..: 8 8 8 8 8 8 8 8 > 8 > 8 ... > $ STATUS : num 1 1 1 1 1 1 1 1 1 1 ... > $ SPECIES : Factor w/ 25 levels "AGWT","AMCO",..: 10 10 7 7 3 5 5 5 > 5 > 2 ... > $ SOCIAL_STATUS : chr "4" "1" "4" "1" ... > $ COUNT_OF_GROUPS: num 1 1 1 1 1 3 3 3 1 2 ... > $ MALE : num 1 1 1 1 1 1 1 1 1 0 ... > $ FEMALE : num 1 0 1 0 1 1 1 1 0 0 ... > $ NOSEX : num 0 0 0 0 0 0 0 0 0 2 ... > $ UPLAND : num 0 0 0 0 0 0 0 0 0 0 ... > $ TAG : num 0 0 0 0 0 0 0 0 0 0 ... > > [[alternative HTML version deleted]] > > ______________________________________________ > R-help@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >-- Henrique Dallazuanna Curitiba-Paraná-Brasil 25° 25' 40" S 49° 16' 22" O [[alternative HTML version deleted]]
Bert Gunter
2009-Jun-24 16:53 UTC
[R] How to avoid ifelse statement converting factor to character
Explicitly convert it to a factor... data$SOCIAL_STATUS<-factor(ifelse(data$SOCIAL_STATUS=="B" & data$MALE>4, "C", data$SOCIAL_STATUS)) However, note that this would, in general, change the levels attribute to the levels actually present in the converted vector. If you wish to (and it makes sense to) retain the original levels, you will have to set them explicitly in the factor() call, I believe. I believe the reason this occurs is that ifelse() could (and usually would) change the values present, which would mess up the levels of the factor. So default conversion to character seems like desirable behavior to me. It's then up to the user to recreate the factor as appropriate. Bert Gunter Genentech Nonclinical Biostatistics -----Original Message----- From: r-help-bounces at r-project.org [mailto:r-help-bounces at r-project.org] On Behalf Of Mark Na Sent: Wednesday, June 24, 2009 9:34 AM To: r-help at r-project.org Subject: [R] How to avoid ifelse statement converting factor to character Hi R-helpers, Please see the below R output. The problem is that after running the ifelse statement, data$SOCIAL_STATUS is converted from a factor to a character. Is there some way I can avoid this conversion? Thanks in advance, Mark Na> str(data)'data.frame': 2100 obs. of 11 variables: $ DATE : Factor w/ 5 levels "4-Jun-09","7-May-09",..: 1 1 1 1 1 1 1 1 1 1 ... $ POND_ID : Factor w/ 113 levels "10","18","19",..: 8 8 8 8 8 8 8 8 8 8 ... $ STATUS : num 1 1 1 1 1 1 1 1 1 1 ... $ SPECIES : Factor w/ 25 levels "AGWT","AMCO",..: 10 10 7 7 3 5 5 5 5 2 ... $ SOCIAL_STATUS : Factor w/ 8 levels "A","B","D","E",..: 4 1 4 1 4 4 4 4 1 6 ... $ COUNT_OF_GROUPS: num 1 1 1 1 1 3 3 3 1 2 ... $ MALE : num 1 1 1 1 1 1 1 1 1 0 ... $ FEMALE : num 1 0 1 0 1 1 1 1 0 0 ... $ NOSEX : num 0 0 0 0 0 0 0 0 0 2 ... $ UPLAND : num 0 0 0 0 0 0 0 0 0 0 ... $ TAG : num 0 0 0 0 0 0 0 0 0 0 ...> data$SOCIAL_STATUS<-ifelse(data$SOCIAL_STATUS=="B" & data$MALE>4, "C",data$SOCIAL_STATUS)> str(data)'data.frame': 2100 obs. of 11 variables: $ DATE : Factor w/ 5 levels "4-Jun-09","7-May-09",..: 1 1 1 1 1 1 1 1 1 1 ... $ POND_ID : Factor w/ 113 levels "10","18","19",..: 8 8 8 8 8 8 8 8 8 8 ... $ STATUS : num 1 1 1 1 1 1 1 1 1 1 ... $ SPECIES : Factor w/ 25 levels "AGWT","AMCO",..: 10 10 7 7 3 5 5 5 5 2 ... $ SOCIAL_STATUS : chr "4" "1" "4" "1" ... $ COUNT_OF_GROUPS: num 1 1 1 1 1 3 3 3 1 2 ... $ MALE : num 1 1 1 1 1 1 1 1 1 0 ... $ FEMALE : num 1 0 1 0 1 1 1 1 0 0 ... $ NOSEX : num 0 0 0 0 0 0 0 0 0 2 ... $ UPLAND : num 0 0 0 0 0 0 0 0 0 0 ... $ TAG : num 0 0 0 0 0 0 0 0 0 0 ... [[alternative HTML version deleted]] ______________________________________________ R-help at r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.
Stavros Macrakis
2009-Jun-24 18:51 UTC
[R] How to avoid ifelse statement converting factor to character
On Wed, Jun 24, 2009 at 12:34 PM, Mark Na<mtb954 at gmail.com> wrote:> The problem is that after running the ifelse statement, data$SOCIAL_STATUS > is converted from a factor to a character. > Is there some way I can avoid this conversion?I'm afraid that ifelse has very bizarre semantics when the yes and no arguments don't have the same, atomic vector, type. The quick workaround for the bizarre semantics (though it can have a significant efficiency cost) is this: unlist( ifelse ( condition, as.list( yes ), as.list( no ) ) ) (This isn't perfect, either, but...) Take a look at the man page for details and the warning: The mode of the result may depend on the value of 'test', and the class attribute of the result is taken from 'test' and may be inappropriate for the values selected from 'yes' and 'no'. Some consequences of the definition of ifelse are: Even if the classes of the yes and no arguments are identical, the result does not necessarily have that class: ifelse(TRUE,as.raw(4),as.raw(5)) => error ifelse(TRUE,factor('x'),factor('x')) => 1 (integer) dates <- as.POSIXct(c('1990-1-1','2000-1-1')) ifelse(c(TRUE,FALSE),dates,dates) => 631170000 946702800 (double) ifelse(c(TRUE,FALSE),factor(c('x','y')),factor(c('y','x'))) => 1 1 If they have different classes, things get stranger: ifelse(c(TRUE,FALSE),c("a","b"),factor(c("c","d"))) => "a" "2" ifelse(c(TRUE,FALSE),list(1,2),as.raw(4)) [[1]] [1] 1 [[2]] [1] 04 Result is order-dependent: ifelse(c(TRUE,FALSE),as.raw(4),list(1,2)) Error in ans[test & !nas] <- rep(yes, length.out = length(ans))[test & : incompatible types (from raw to logical) in subassignment type fix Welcome to R! -s
clint
2011-Nov-04 23:33 UTC
[R] How to avoid ifelse statement converting factor to character
most all those posts were right in sourcing the problem....its just that nobody actually offered a viable solution the problem is that the new level "C" was not one of the original levels in $social status add "C" as a level and then just do the ol fashioned way and it works just fine do this: data$SOCIAL_STATUS <- factor(data$SOCIAL_STATUS, levels c(levels(data$SOCIAL_STATUS), "C")) then this: data$SOCIAL_STATUS<-ifelse(data$SOCIAL_STATUS=="B" & data$MALE>4, "C", data$SOCIAL_STATUS) it is sooo much more helpful when someone who has addressed the specific problem being asked replies instead of people just throwing random ideas out there -- View this message in context: http://r.789695.n4.nabble.com/How-to-avoid-ifelse-statement-converting-factor-to-character-tp895726p3992067.html Sent from the R help mailing list archive at Nabble.com.
David Winsemius
2011-Nov-05 01:40 UTC
[R] How to avoid ifelse statement converting factor to character
On Nov 4, 2011, at 7:33 PM, clint <clint at ucsd.edu> wrote:> most all those posts were right in sourcing the problem....its just that > nobody actually offered a viable solutionVery few problems that are posed with a test dataset go unanswered.> > the problem is that the new level "C" was not one of the original levels in > $social status > > add "C" as a level and then just do the ol fashioned way and it works just > fine > > do this: > data$SOCIAL_STATUS <- factor(data$SOCIAL_STATUS, levels > c(levels(data$SOCIAL_STATUS), "C")) > > then this: > data$SOCIAL_STATUS<-ifelse(data$SOCIAL_STATUS=="B" & data$MALE>4, "C", > data$SOCIAL_STATUS) > > it is sooo much more helpful when someone who has addressed the specific > problem being asked replies instead of people just throwing random ideas out > there >Just a little Friday night trolling? This was a posting from 2 years ago. -- David> > -- > View this message in context: http://r.789695.n4.nabble.com/How-to-avoid-ifelse-statement-converting-factor-to-character-tp895726p3992067.html > Sent from the R help mailing list archive at Nabble.com. >This is a mailing list. Nabble users who fail to include context who replying to ancient threads should not be throwing stones.> ______________________________________________ > R-help at r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code.