How do I transpose a tibble() in R [duplicate]
Asked Answered
C

3

30

In R the t() function is really meant for matrices. When I try to transpose my tibble with t() I end up with a matrix. A matrix can't be made into a tibble with tibble(). I end up spending time storing column names as variables and attaching them as I try to re-make a transposed version of my tibble.

Question: What is the simplest way to transpose a tibble where the first column should become the column names of the new tibble and the old column names become the first column of my new tibble.

Cymric answered 14/3, 2017 at 15:33 Comment(5)
as_tibble(cbind(nms = names(df), t(df)))Arid
The only problem with this is that all of my doubles turned into characters.Cymric
sapply(df[,2:length(df)],as.numeric) I think this fixed itCymric
Nope, sapply(df[,2:length(df)],as.numeric) did not work.Cymric
Late for it, but you could convert to numeric with %>% mutate_at(2:nrow(df), as.numeric)Ourselves
B
36

As Sotos has mentioned it, you just need to re-declare your matrix as a tibble:

as_tibble(cbind(nms = names(df), t(df)))
Blake answered 14/3, 2017 at 16:17 Comment(1)
This did not work for me and added the original column of rownames as an additional, unwanted row in the resulting tibble, and not as the names of the columns like it should.Nausea
M
18

Solution here: https://mcmap.net/q/472520/-transposing-data-frames-duplicate

library(dplyr)
library(tidyr)
df %>%
    gather(key = var_name, value = value, 2:ncol(df)) %>% 
    spread_(key = names(df)[1],value = 'value')
Matinee answered 14/3, 2017 at 16:4 Comment(0)
D
14

I was faced with the same problem and tried all the above-mentioned solutions and realized that none of them actually preserve the names of the columns.

Here is, in my opinion, a better way to do the same:

# attaching needed libraries
library(dplyr)
library(data.table)
library(tibble)

# defining the dataframe
df <- cbind.data.frame(x = rnorm(10), y = rnorm(10))

# custom function to transpose while preserving names
transpose_df <- function(df) {
  t_df <- data.table::transpose(df)
  colnames(t_df) <- rownames(df)
  rownames(t_df) <- colnames(df)
  t_df <- t_df %>%
    tibble::rownames_to_column(.data = .) %>%
    tibble::as_tibble(.)
  return(t_df)
}

# using the function
transpose_df(df)
#> # A tibble: 2 x 11
#>   rowname    `1`   `2`     `3`    `4`      `5`   `6`    `7`    `8`    `9`
#>   <chr>    <dbl> <dbl>   <dbl>  <dbl>    <dbl> <dbl>  <dbl>  <dbl>  <dbl>
#> 1 x       -1.38  0.752  1.22    0.296 -0.00298 1.50  -0.719 -0.503 -0.114
#> 2 y        0.618 0.304 -0.0559 -1.27   0.0806  0.156  0.522  0.677  0.532
#> # ... with 1 more variable: `10` <dbl>

Created on 2018-02-17 by the reprex package (v0.2.0).

Dariadarian answered 17/2, 2018 at 6:53 Comment(4)
I like this, but if the input is already tibble, and not data.frame, it fails with Error in tibble::rownames_to_column(.data = .) : is.data.frame(df) is not TRUE. Can you fix it to behave as expected with a tibble input?Liz
I just tried it with a tibble input and there is no issue. Are you sure you are entering a data frame, and not some other data structure?Dariadarian
Indeed, I just learned purrr:map returns a list and not a df ... purrr::map_dfr is the way to go then. Sorry. I can delete my comment then.Liz
Thanks, based on the use of t(), this worked for me: {r} transpose_df <- function(df) { df %>% t() %>% #Tranpose, but function is for matrices. Return Matrix as.data.frame() %>% #Force to be dataframe tibble::rownames_to_column(var = "rowname") %>% #Resave first column from rownames janitor::row_to_names(row_number = 1) #Resave column headers from first row. }Whippet

© 2022 - 2024 — McMap. All rights reserved.