tidyr gather() in R: Wide to Long (Superseded by pivot_longer)
The gather() function in tidyr reshapes data from WIDE to LONG format. As of tidyr 1.0, it is SUPERSEDED by pivot_longer(); existing code works but new code should use pivot_longer.
df |> gather(key = "var", value = "val", a, b, c) # superseded df |> pivot_longer(cols = c(a, b, c), names_to = "var", values_to = "val") # modern df |> gather(key, value, -id) # gather all but id df |> pivot_longer(-id, names_to = "key", values_to = "value") # modern
Need explanation? Read on for examples and pitfalls.
What gather() did in one sentence
gather(data, key, value, cols) took a wide data frame and stacked the named columns into TWO new columns: a key column (column names) and a value column (the values). Since tidyr 1.0, it is superseded by the more flexible pivot_longer().
Migration
Replace gather(key = X, value = Y, cols) with pivot_longer(cols, names_to = X, values_to = Y).
pivot_longer() supports more than one value column at once and has cleaner argument naming. For new code, always use pivot_longer.Five common patterns (legacy)
1. Standard gather
Modern: pivot_longer(-id, names_to = "var", values_to = "val").
2. Specific columns
Modern: pivot_longer(c(a, b, c), names_to = "metric", values_to = "value").
3. Tidyselect
Modern: pivot_longer(starts_with("score_"), names_to = "key", values_to = "val").
4. Drop NA
Modern: pivot_longer(c(a, b), names_to = "var", values_to = "val", values_drop_na = TRUE).
5. Verify same result
gather() vs pivot_longer()
| Feature | gather() | pivot_longer() |
|---|---|---|
| Wide -> long | Yes | Yes |
| Multiple value columns | No | Yes |
| names_pattern (regex) | No | Yes |
| names_sep (split key) | No | Yes |
| values_drop_na | Yes (na.rm) | Yes |
| Status | Superseded | Recommended |
A practical migration
Argument names are explicit; positional args of gather were less obvious.
Common pitfalls
Pitfall 1: confusing key and value. gather takes (key, value, ...) where key gets the COLUMN names and value gets the values. pivot_longer makes this explicit with names_to and values_to.
Pitfall 2: forgetting tidyselect. gather uses tidyselect for its column args. So does pivot_longer.
gather and spread were superseded in tidyr 1.0 (2019). That's many years ago. Most current tutorials use pivot_longer/pivot_wider. Migrating saves you from outdated examples.Try it yourself
Try it: Reshape a wide data frame to long using BOTH gather and pivot_longer, then verify identical output. Save check to ex_check.
Click to reveal solution
Explanation: For simple wide-to-long, both produce identical output.
Related tidyr functions
After understanding gather's deprecation, look at:
pivot_longer(): modern replacementpivot_wider(): opposite directiontidyr::spread(): also supersededtidyr::unite(): combine columns into onetidyr::separate_wider_delim(): split column
FAQ
Is gather deprecated in tidyr?
Superseded since tidyr 1.0 (2019). Use pivot_longer() for new code.
What is the modern replacement for gather?
pivot_longer(cols, names_to = "key", values_to = "value").
Why was gather superseded?
It couldn't handle multiple value columns or complex name parsing. pivot_longer is a strict superset.
Are gather and spread both superseded?
Yes. gather -> pivot_longer; spread -> pivot_wider. Both since tidyr 1.0.
Will gather be removed?
Possibly in a future major version. Migrate proactively.