rajomato
rajomato

Reputation: 1177

R transposing numeric data.frame results in character variables

I've got a data.frame which contains a character variable and multiple numeric variables, something like this:

sampleDF <- data.frame(a = c(1,2,3,"String"), b = c(1,2,3,4), c= c(5,6,7,8), stringsAsFactors = FALSE)

Which looks like this:

       a b c
1      1 1 5
2      2 2 6
3      3 3 7
4 String 4 8

I'd like to transpose this data.frame and get it to look like this:

  V1 V2 V3     V4
1  1  2  3 String
2  1  2  3      4
3  5  6  7      8

I tried

c<-t(sampleDF)

as well as

d<-transpose(sampleDF)

but both these methods result in V1, V2 and V3 now being of characer type despite only having numeric values.

I know that this has already been asked multiple times. However, I haven't found a suitable answer for why in this case V1, V2 and V3 are also being converted to character.

Is there any way how ensure that these column stay numeric?

Thanks a lot any apologies already for the duplicate nature of this question.

EDIT:

as.data.frame(t(sampleDF)

Does not solve the problem:

'data.frame':   3 obs. of  4 variables:
 $ V1: Factor w/ 2 levels "1","5": 1 1 2
  ..- attr(*, "names")= chr  "a" "b" "c"
 $ V2: Factor w/ 2 levels "2","6": 1 1 2
  ..- attr(*, "names")= chr  "a" "b" "c"
 $ V3: Factor w/ 2 levels "3","7": 1 1 2
  ..- attr(*, "names")= chr  "a" "b" "c"
 $ V4: Factor w/ 3 levels "4","8","String": 3 1 2
  ..- attr(*, "names")= chr  "a" "b" "c"

Upvotes: 1

Views: 4499

Answers (1)

akrun
akrun

Reputation: 887213

After transposing it, convert the columns to numeric with type.convert

out <- as.data.frame(t(sampleDF), stringsAsFactors = FALSE)
out[] <- lapply(out, type.convert, as.is = TRUE)
row.names(out) <- NULL
out
#   V1 V2 V3     V4
#1  1  2  3 String
#2  1  2  3      4
#3  5  6  7      8

str(out)
#'data.frame':  3 obs. of  4 variables: 
#  $ V1: int  1 1 5
#  $ V2: int  2 2 6
#  $ V3: int  3 3 7    
#  $ V4: chr  "String" "4" "8"

Or rbind the first column converted to respective 'types' with the transposed other columns

rbind(lapply(sampleDF[,1], type.convert, as.is = TRUE), 
               as.data.frame(t(sampleDF[2:3])))

NOTE: The first method would be more efficient


Or another approach would be to paste the values together in each column and then read it again

read.table(text=paste(sapply(sampleDF, paste, collapse=" "), 
     collapse="\n"), header = FALSE, stringsAsFactors = FALSE)
#  V1 V2 V3     V4
#1  1  2  3 String
#2  1  2  3      4
#3  5  6  7      8

Or we can convert the 'data.frame' to 'data.matrix' which changes the character elements to NA, use the is.na to find the index of elements that are NA for replacing with the original string values

m1 <- data.matrix(sampleDF)
out <- as.data.frame(t(m1))
out[is.na(out)] <- sampleDF[is.na(m1)]

Or another option is type_convert from readr

library(dplyr)
library(readr)
sampleDF %>% 
     t %>%
     as_data_frame %>%
     type_convert
# A tibble: 3 x 4
#     V1    V2    V3 V4    
#   <int> <int> <int> <chr> 
#1     1     2     3 String
#2     1     2     3 4     
#3     5     6     7 8     

Upvotes: 4

Related Questions