swcarpentry / r-novice-gapminder

R for Reproducible Scientific Analysis
http://swcarpentry.github.io/r-novice-gapminder/
Other
164 stars 538 forks source link

adding rows #436

Closed pandeyravi15 closed 6 years ago

pandeyravi15 commented 6 years ago

Can not we use rbind function as cbind , like newRow <- c("tortoiseshell", 3.3, TRUE, 9) instead of list


Thanks for contributing! If this contribution is for instructor training, please send an email to checkout@carpentries.org with a link to this contribution so we can record your progress. You’ve completed your contribution step for instructor checkout just by submitting this contribution.

Please keep in mind that lesson maintainers are volunteers and it may be some time before they can respond to your contribution. Although not all contributions can be incorporated into the lesson materials, we appreciate your time and effort to improve the curriculum. If you have any questions about the lesson maintenance process or would like to volunteer your time as a contribution reviewer, please contact Kate Hertweck (k8hertweck@gmail.com).


zyqfrog10 commented 6 years ago

Yes. You can use vector instead of list. The following code will add a new row as in the instruction.

newRow <- c("tortoiseshell", 3.3, TRUE, 9)
levels(cats$coat) <- c(levels(cats$coat), "tortoiseshell")
cats <- rbind(cats, newRow)
jcoliver commented 6 years ago

Thanks @pandeyravi15 and @zyqfrog10 . Using a vector to add a new row to a data frame will not work as intended. This is because all elements of a vector must be of the same type. When the vector newRow is declared, it coerces every element to be of type character (this occurs without any messaging). Additionally, when that vector is added to the data frame via rbind, all columns in the data frame are then coerced to be of type character. This also occurs without any warnings or errors from R, so it seems like it worked. Running summary before and after the addition of newRow illustrates this behavior:

cats <- data.frame(coat = c("calico", "black", "tabby"), 
                    weight = c(2.1, 5.0,3.2), 
                    likes_string = c(TRUE, FALSE, TRUE))
summary(cats) # The three columns are type factor, float, and logical
#     coat       weight      likes_string   
# black :1   Min.   :2.100   Mode :logical  
# calico:1   1st Qu.:2.650   FALSE:1        
# tabby :1   Median :3.200   TRUE :2        
#            Mean   :3.433                  
#            3rd Qu.:4.100                  
#            Max.   :5.000                  

newRow <- c("tortoiseshell", 3.3, TRUE, 9)
levels(cats$coat) <- c(levels(cats$coat), "tortoiseshell")
cats <- rbind(cats, newRow)
summary(cats) # weight and likes_string are now type character
#            coat      weight          likes_string      
# black        :1   Length:4           Length:4          
# calico       :1   Class :character   Class :character  
# tabby        :1   Mode  :character   Mode  :character  
# tortoiseshell:1

By using a list, we preserve the type of each of the elements (factor, float, and logical, respectively).