Skip to main content
v2026.11,858 entries · CC-BY 4.0
LAC HealthMedical & Research SuppliesReagents, PPE & instruments — chain-of-custody documented.Fast, traceable sourcing built for regulated research environments, from bench consumables to instrumentation.Shop lac.us CodeCASRAIlac.us

R Transpose: How to Transpose a Data Frame with t() and data.table

How to transpose in R with t() and data.table::transpose(): the matrix coercion, names handling, and when you need pivot_longer instead.

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]:

  1. Create the matrix: a <- matrix(1:30, 5, 6)
  2. Transpose it: ta <- t(a)
  3. Check the dimensions: dim(a) is 5 6 and dim(ta) is 6 5.

2. Transpose a data frame in R

  1. Create or load the data frame, for example df <- data.frame(x = 1:5, y = 6:10).
  2. Check what you start with: class(df) and str(df).
  3. Transpose: tdf <- t(df).
  4. Check what you ended up with: class(tdf). It is a matrix, and the 5 rows and 2 columns of df are now 2 rows and 5 columns.
  5. 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:

  1. tdf <- as.data.frame(t(df[, -1]))
  2. 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 with as.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 use data.table::transpose() with make.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)

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about R Transpose: How to Transpose a Data Frame with t() and data.table

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →