Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixed type in vector (rbind dataframe without typeconversion)

In R a vector can not contain different types. Everything must e.g. be an integer or everything must be character etc. This gives me headaches sometimes. E.g. when I want to add a margin to a data.frame, and need some coloumns to be numeric and other to be characters.

Below a reproducible example:

# dummy data.frame
set.seed(42)
test <- data.frame("name"=sample(letters[1:4], 10, replace=TRUE),
                   "val1" = runif(10,2,5),
                   "val2"=rnorm(10,10,5),
                   "Status"=sample(c("In progres", "Done"), 10, replace=TRUE),
                   stringsAsFactors = FALSE)

# check that e.g. "val1" is indeed numeric
is.numeric(test$val1)
# TRUE
# create coloumn sums for my margin.
tmpSums <- colSums(test[,c(2:3)])
# Are the sums numeric?
is.numeric(tmpSums[1])
#TRUE
# So add the margin
test2 <- rbind(test, c("All", tmpSums, "Mixed"))
# is it numeric
is.numeric(test2$val1)
#FALSE
# DAMN. Because the vector `c("All", tmpSums, "Mixed")` contains strings
# the whole vector is forced to be a string. And when doing the rbind
# the orginal data.frame is forced to a new type also

# my current workaround is to convert back to numeric
# but this seems convoluted, back and forward.
valColoumns <- grepl("val", names(test2))
test2[,valColoumns] <- apply(test2[,valColoumns],2, function(x) as.numeric(x))
is.numeric(test2$val1)
# finally. It works.

there must be an easier / better way?

like image 760
Andreas Avatar asked Feb 24 '16 02:02

Andreas


1 Answers

Use a list object in your rbind, like:

test2 <- rbind(test, c("All", unname(as.list(tmpSums)), "Mixed"))

Where the second argument to rbind is a list, removed of conflicting names that will cause rbind to fail:

c("All", unname(as.list(tmpSums)), "Mixed")
#[[1]]
#[1] "All"
# 
#[[2]]
#[1] 37.70092
#
#[[3]]
#[1] 91.82716
#
#[[4]]
#[1] "Mixed"
like image 110
thelatemail Avatar answered Sep 21 '22 22:09

thelatemail