tibble as_tibble_row() in R: One Row at a Time
The as_tibble_row() function in the tibble package converts a named vector or a length-1 list into a one-row tibble, with each element becoming a column. It is the standard tool for building tibbles record-by-record from named scalars.
as_tibble_row(c(x = 1, y = 2, z = 3)) # named vector to 1 row as_tibble_row(list(a = 1, b = "hi")) # mixed-type named list as_tibble_row(c(1, 2, 3)) # errors: needs names as_tibble_row(c(a = 1, a = 2), .name_repair = "unique") # dedupe names purrr::map_dfr(seq, ~ as_tibble_row(.x)) # row-by-row build as_tibble_row(list(id = 1, vals = list(1:3))) # list-column in one row as_tibble_row(setNames(1:3, c("a","b","c"))) # vector via setNames
Need explanation? Read on for examples and pitfalls.
What as_tibble_row() does in one sentence
as_tibble_row() turns a single named record into a one-row tibble. You pass a named vector or a length-1 list, and the function returns a tbl_df with one row and as many columns as there are names. Unlike tibble() or as_tibble(), this function is opinionated about producing exactly one row.
The use case is record-shaped data: a function returning named summary statistics, a dictionary from a JSON API, an iteration inside a for loop that computes a fresh record. as_tibble_row() lifts the wide-by-name shape into the tidyverse without manual reshaping.
Syntax
as_tibble_row() is a thin wrapper over as_tibble() with .rows = 1. It has a fixed contract: input must be named, output is always one row.
The full signature is:
as_tibble_row(x, .name_repair = c("check_unique", "unique", "universal", "minimal"))
xis a named vector or a list (each element length 1, or a list itself for list-columns)..name_repaircontrols duplicate or syntactically invalid names:"check_unique"(default, errors on duplicates),"unique"(auto-suffix),"minimal"(keep as-is),"universal"(also fix syntax).
The result always has exactly one row and class(c("tbl_df", "tbl", "data.frame")).
as_tibble_row() over manual tibble() calls when names come from data. Writing tibble(mpg = 21, cyl = 6, hp = 110) requires you to know the names at write time. as_tibble_row(record) works with whatever names the upstream code produced, which is exactly what you want inside lapply(), purrr::map(), or any pipeline that processes records dynamically.Five common patterns
1. Convert a named numeric vector
Every element of the vector becomes one column. The numeric type carries through, so column types match the source vector exactly.
2. Convert a mixed-type named list
Lists are the natural input when columns mix types. Each element keeps its own type, so the resulting tibble has <dbl>, <chr>, and <lgl> columns without coercion.
3. Build row-by-row in a loop
This is the classic record-accumulator pattern. Each iteration produces one row; rbind() stitches them into the final frame. The dplyr::bind_rows() and purrr::map_dfr() shortcuts (next pattern) do the same thing more concisely.
4. Combine with purrr::map_dfr
map_dfr() calls the function for each input, expects a tibble row out, and binds the results. Paired with as_tibble_row(), it replaces dozens of lines of for-loop bookkeeping with one expression.
5. Create a list-column inside the row
When a list element is itself a list of length 1, that cell becomes a list-column. This is how you store nested objects (vectors, models, even tibbles) inside a single row, ready for tidyr::unnest() or purrr::map() later.
as_tibble_row() vs as_tibble() vs tibble()
The three constructors differ in what they accept and how many rows they emit. as_tibble_row() always produces one row from a named record. as_tibble() coerces an existing rectangular object preserving its shape. tibble() builds from raw vectors with the row count determined by the longest input.
| Behavior | as_tibble_row() |
as_tibble() |
tibble() |
|---|---|---|---|
| Input | Named vector or list | data.frame, list, matrix | Bare named vectors |
| Rows in output | Always 1 | Same as input | Length of longest input |
| Names required | Yes (errors without) | Yes (or repaired) | From argument names |
| Mixed types | Yes (via list input) | Yes | Yes |
| Recycling | None | None | Length 1 to longest |
| Typical use | One record at a time | Coerce existing object | Inline construction |
Decision rule:
- Reach for
as_tibble_row()when each unit of work produces a named scalar record. - Reach for
tibble()when you have parallel vectors and know their names statically. - Reach for
as_tibble()when you already have a data.frame, list, or matrix to promote.
as_tibble_row() is the natural pair to purrr::map_dfr(). Together they form the canonical "for-each-input, build-a-record, bind-them-all" pattern. Once you internalize that pairing, most loops that accumulate results collapse into a single map_dfr() call, with as_tibble_row() doing the per-iteration shape lift.Common pitfalls
Pitfall 1: unnamed input errors immediately. The function requires names; bare numeric vectors trigger a hard error, not a fallback.
setNames() is the quickest fix. For programmatic naming, build the names vector first and apply it before the conversion.
Pitfall 2: vector elements longer than 1 break the 1-row contract. Every element of a vector input must be a scalar, and every list element must be length 1 (or a wrapped list for list-columns).
The error message can confuse newcomers because it talks about "compatible sizes" while the function is explicitly designed for one row. The fix is always: either reduce the long element to a scalar, or wrap it in list() to make it a list-column.
as_tibble_row() is NOT the same as as_tibble() on a list. Calling as_tibble(list(a = 1, b = 2)) returns a 1-row, 2-column tibble in the common case, but if any element has length greater than 1 it creates multiple rows. as_tibble_row() will error in that case. Use the row variant when you need a guarantee that the output is exactly one row, no matter what the input looks like.Pitfall 3: forgetting to bind the rows. A single as_tibble_row() call inside a loop is useless without an aggregator. Always pair it with do.call(rbind, ...), dplyr::bind_rows(), or purrr::map_dfr().
Try it yourself
Try it: For each cylinder count in mtcars (4, 6, 8), compute the mean mpg and number of cars, then assemble the three records into a single tibble called ex_summary.
Click to reveal solution
Explanation: map_dfr() walks the three cylinder values, calls the function once per value, and binds the resulting one-row tibbles into a 3-row frame. as_tibble_row() does the per-iteration shape lift from named numeric vector to one row.
Related tibble functions
After mastering as_tibble_row(), look at:
as_tibble_col(): the column-shaped twin, turns a named vector into a one-column tibble withnameandvaluecolumns.tibble(): build a tibble inline from raw named vectors of any length.as_tibble(): coerce an existing data.frame, list, or matrix into a tibble.tribble(): row-by-row construction with a literal syntax, good for fixed lookup tables.enframe(): another named-vector entry point, but always emits two columns (name, value).add_row(): append a single record to an existing tibble.
For the full API, the official as_tibble_row() documentation lists every method and option.
FAQ
What is the difference between as_tibble_row() and as_tibble() in R?
as_tibble_row() always returns exactly one row, taking a named vector or length-1 list as input. as_tibble() is the general coercer for already-rectangular objects (data frames, matrices, lists of equal-length vectors) and returns as many rows as the input shape implies. Reach for as_tibble_row() inside loops or map_dfr() calls where each unit of work produces one record. Reach for as_tibble() when you have a complete data frame or list to promote into the tidyverse.
Why does as_tibble_row() error on unnamed input?
Tibbles require named columns, and as_tibble_row() maps each input element to a column. With no names, the function fails fast rather than inventing labels like V1, V2. Fix by attaching names with setNames(x, c("a", "b", "c")) or purrr::set_names() before passing the vector. If the data has no meaningful names, tibble() with positional construction is more honest about what you are doing.
How do I create a list-column with as_tibble_row()?
Wrap the multi-element value in list() so it becomes a single list element of length 1. as_tibble_row(list(id = 1, vals = list(c(1, 2, 3)))) puts the three-element numeric vector inside one cell. Without the outer list(), the function errors with a length-mismatch message. List-columns are the standard way to nest vectors, models, or other tibbles inside one row.
How is as_tibble_row() different from tibble()?
tibble() builds from raw named arguments: tibble(a = 1:3, b = 4:6). You write names and values literally. as_tibble_row() takes one already-constructed named object and lifts it into a one-row tibble. Use tibble() when names are known at write time. Use as_tibble_row() when names come from upstream data, often inside a loop or map() producing one record per iteration.
Can I use as_tibble_row() with a data.frame row?
Indirectly. Extract a single row as a named list with as.list(df[i, ]), then pass it in: as_tibble_row(as.list(mtcars[1, ])). Useful for plucking one record from a larger frame and re-emitting it as a standalone tibble, for example to bind into a different schema or to attach as a manifest.