39

I have a big dataframe, but small example would be like this:

mydf <- data.frame(A = c(letters[1:10]), M1 = c(11:20), M2 = c(31:40), M3 = c(41:50))

I want to transpose the dataframe and maintain the column 1 (A) as column heading ( letter[1:10]) as variable names. The following are scratch trials of unsuccessful codes.

tmydf = data.frame(t(mydf))
names(tmydf) <- tmydf[1,]

Thanks;

Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
jon
  • 11,186
  • 19
  • 80
  • 132
  • 1
    You don't need to call `c` for sequences created with a colon. So `11:20` is the same as `c(11:20)`, and `letters[1:10]` is the same as `c(letters[1:10])`. – Richie Cotton Nov 01 '11 at 17:44

5 Answers5

76

Here is one way

tmydf = setNames(data.frame(t(mydf[,-1])), mydf[,1])
Ramnath
  • 54,439
  • 16
  • 125
  • 152
  • There several similar threads around, like this: http://stackoverflow.com/questions/6645524/what-is-the-best-way-to-transpose-a-data-frame-in-r-and-to-set-one-of-the-column or this: http://stackoverflow.com/questions/6778908/r-transposing-a-data-frame . I like your answer best so far, +1. It's simple, reliable and keeps numeric as it is. – Matt Bannert Dec 06 '12 at 15:35
10

Something like this perhaps:

tmp <- as.data.frame(t(mydf[,-1]))
> colnames(tmp) <- mydf$A
> tmp
    a  b  c  d  e  f  g  h  i  j
M1 11 12 13 14 15 16 17 18 19 20
M2 31 32 33 34 35 36 37 38 39 40
M3 41 42 43 44 45 46 47 48 49 50
joran
  • 169,992
  • 32
  • 429
  • 468
6

One more way using janitor::row_to_names() with dplyr/magrittr pipes

mydf <- data.frame(A = c(letters[1:10]), M1 = c(11:20), M2 = c(31:40), M3 = c(41:50))


library(janitor, warn.conflicts = F)
library(dplyr, warn.conflicts = F)
mydf %>% t %>% as.data.frame() %>% row_to_names(1)

#>     a  b  c  d  e  f  g  h  i  j
#> M1 11 12 13 14 15 16 17 18 19 20
#> M2 31 32 33 34 35 36 37 38 39 40
#> M3 41 42 43 44 45 46 47 48 49 50

Created on 2021-06-17 by the reprex package (v2.0.0)

AnilGoyal
  • 25,297
  • 4
  • 27
  • 45
5

You can use the pivot_longer and pivot_wider functions from the tidyr package.

library(tidyr)
mydf%>%
  pivot_longer(cols=c(-A),names_to="Original_Vars")%>%
  pivot_wider(names_from=c(A))

The pivot_longer makes a column called "Original_Vars", and a new column called value. If you stopped here, you'd have a row for each combination of your A variable, your "Original_Vars" (being M1, M2, and M3 here), and the value associated with that pairing.

The pivot_wider then takes all your values from the "A" column and turns them into columns, using the values from the value column we created with pivot_longer to fill in.

Pake
  • 968
  • 9
  • 24
  • This is exactly what I was looking for (a tidyverse solution)! SO needs a way to add tags to specific answers. In this case, I'd choose: `dplyr`, `tidyr`, and `tidyverse`. – D. Woods Aug 25 '21 at 21:18
1

Data.table variante from Ramnath with indicating in string the variable name wanted.

mydf <- data.table(A = c(letters[1:10]), M1 = c(11:20), M2 = c(31:40), M3 = c(41:50))
tmydf <- setNames(data.table(t(mydf[,-"A"])), mydf[["A"]])
Dorian Grv
  • 421
  • 5
  • 9