Written and maintained by CASRAI Editorial Board
Last updated
To transpose in R, call t(x) from base R: it swaps the rows and columns of a matrix or data frame. The detail most guides skip is that t() always returns a matrix, not a data frame, because a data frame is first coerced with as.matrix(). That one step explains most surprises people hit when they transpose a data frame in R: columns turning into text, lost column names, and $ refusing to work on the result.
What it is used for in research
Transposing turns observations into variables and variables into observations. Researchers typically need it when an instrument or database export arrives with samples across the columns and measurements down the rows, when a package expects the opposite orientation, or when a small summary table reads better rotated. If what you really want is to restructure a table from wide to long (one row per measurement), that is a reshape, not a transpose; see the FAQ below.
Install or access (official source only)
t() is part of base R, so there is nothing to install beyond R itself, which is distributed through CRAN (cran.r-project.org). Its reference page is in the R manual: t: Matrix Transpose. The alternatives covered below are CRAN packages, installed from within R:
install.packages("data.table")
install.packages("tidyr")
Step-by-step task: transpose a matrix or data frame in R
1. Transpose a matrix
The R manual’s own example builds a 5 by 6 matrix and transposes it, so that a[i, j] equals ta[j, i]:
- Create the matrix:
a <- matrix(1:30, 5, 6) - Transpose it:
ta <- t(a) - Check the dimensions:
dim(a)is 5 6 anddim(ta)is 6 5.
2. Transpose a data frame in R
- Create or load the data frame, for example
df <- data.frame(x = 1:5, y = 6:10). - Check what you start with:
class(df)andstr(df). - Transpose:
tdf <- t(df). - Check what you ended up with:
class(tdf). It is a matrix, and the 5 rows and 2 columns ofdfare now 2 rows and 5 columns. - If you need a data frame again, wrap the result:
tdf2 <- as.data.frame(t(df)).
3. Keep the first column as the new headers
When the first column holds identifiers (sample names, gene names) that should become column names after the transpose, move it out of the data before transposing, then reattach it as names:
tdf <- as.data.frame(t(df[, -1]))colnames(tdf) <- df[[1]]
With data.table, the same job is built in. The documented usage is transpose(l, fill = NA, ignore.empty = FALSE, keep.names = NULL, make.names = NULL, list.cols = FALSE). The make.names argument takes the name or number of a column in the input to use as the names of the output, and keep.names gives the name of a new first column in the result that records the names of the input.
library(data.table)
DT <- data.table(x = 1:5, y = 6:10)
transpose(DT)
That is a minimal call on a small table. Unlike t(), transpose() returns a list, data.frame or data.table matching its input rather than a matrix.
Output and how to read it
The manual describes the value of t() as a matrix with dim and dimnames constructed appropriately from those of the input, with other attributes except names copied across. In practice, read the result with three checks.
Why does t() return a matrix?
Because the R manual states that a data frame is first coerced to a matrix; see as.matrix. A matrix holds one type only. If every column is numeric or logical, the usual coercion hierarchy applies (logical < integer < double < complex). If any column is character or a factor, non-character columns are converted to text, so the whole transposed result becomes character and numbers can no longer be used in arithmetic until you convert them back, for example with as.numeric().
What happens to row and column names?
The row names of the data frame become the column names of the result, and the column names become the row names. The manual notes that for as.matrix, a data frame with “automatic” row names gets NULL row names by default (the rownames.force argument controls this), so a transposed data frame with default row names has no meaningful column names until you set them.
What happens to a vector?
According to the manual, when x is a vector it is treated as a column, so the result is a 1-row matrix.
Troubleshooting
- Numbers turned into text. At least one column was character or a factor, so the coerced matrix is character. Select the numeric columns before transposing, or convert the result back with
as.numeric(). - “$ operator is invalid for atomic vectors”. You are using
$on a matrix. Wrap the result withas.data.frame()first. - Columns are called V1, V2, … or have no names. The input had automatic row names. Assign
colnames()from the identifier column, or usedata.table::transpose()withmake.names. - A single vector gave a one-row matrix. That is the documented behaviour; use
as.matrix(v)if you want a column instead.
Free alternatives
| Approach | Returns | Names handling (per documentation) | Use when |
|---|---|---|---|
t(x) (base R) |
A matrix | Row and column names swap; automatic row names are dropped by as.matrix |
The data is one type, or you want a matrix |
as.data.frame(t(x)) (base R) |
A data frame | Same as t(); you then set colnames() yourself |
You want to keep working with $ and data frame tools |
data.table::transpose() |
A list, data.frame or data.table matching the input | make.names picks the column that becomes the output names; keep.names stores the input names |
The first column should become the header row |
tidyr::pivot_longer() |
A longer data frame | You set cols, names_to and values_to |
You need long format, which is a reshape, not a transpose |
FAQ
How do I transpose a data frame in R?
Use t(df), and wrap it as as.data.frame(t(df)) if you need a data frame back. The base function coerces the data frame to a matrix first, so mixed column types become character.
How do I keep the first column as headers after I transpose in R?
Remove the first column, transpose the rest, then set colnames() from the removed column. With data.table, pass that column to make.names in transpose().
Is pivot_longer the same as transpose?
No. The tidyr reference describes pivot_longer() as lengthening data, increasing the number of rows and decreasing the number of columns. A transpose swaps rows and columns. For the same idea in other tools, see the reshape command in Stata.
Can I transpose in other software?
Yes. The equivalents are covered in our guides to NumPy transpose and PROC TRANSPOSE in SAS. For other matrix operations in R, see solve() in R, and for a worked statistical test on a prepared data frame, running a t-test in R.
Sources (official docs)
- R Core Team, t: Matrix Transpose, R manual (checked 2026-10-29).
- R Core Team, matrix and as.matrix, R manual (checked 2026-10-29).
- data.table, transpose reference (checked 2026-10-29).
- tidyr, pivot_longer reference (checked 2026-10-29).







