tribble
tribble(...) Description
tribble() builds a tibble by laying out data row by row, reading left to right, the opposite of tibble() which takes column vectors. It is designed for small tables of data where readability matters, such as lookup tables, configuration data, or examples in documentation.
The column names are declared first using the formula syntax (~name), and the actual values follow. This makes the structure immediately visible when you read the code.
tribble() is part of the tibble package, which provides the tbl_df class, a stricter, more predictable reimagining of data.frame.
Arguments
…
Name-value pairs specifying column names and data. Column names must use the formula syntax (~column_name) and must appear before the corresponding values.
tribble(
~name, ~age,
"Alice", 29,
"Bob", 34
)
# # A tibble: 2 × 2
# name age
# <chr> <dbl>
# 1 Alice 29
# 2 Bob 34
The ... arguments are processed with rlang::list2(), which means they support tidyeval unquoting via !! and unquote-splice via !!!.
tribble vs tibble vs data.frame
The three functions create rectangular data in R but with different layouts and constraints:
| Feature | tribble() | tibble() | data.frame() |
|---|---|---|---|
| Layout | Row-by-row | Column-by-column | Column-by-column |
| Column references | Not supported | Sequential evaluation | No |
| List columns | Auto-detected | Auto-detected | No |
| Row names | No | No | Yes |
| Partial match | Errors | Errors | Silent NULL |
| Vector recycling | Errors | Errors | Silent warning |
# tibble: columns evaluated sequentially
tibble(x = 1:3, y = x * 2)
# # A tibble: 3 × 2
# x y
# <int> <dbl>
# 1 1 2
# 2 2 4
# 3 3 6
# tribble: no sequential references — use tribble for this data layout
tribble(
~x, ~y,
1, 2,
2, 4,
3, 6
)
# # A tibble: 3 × 2
# x y
# <int> <dbl>
# 1 1 2
# 2 2 4
# 3 3 6
The tibble() constructor evaluates columns sequentially, which means a column defined later can reference an earlier one. The tribble() constructor, by contrast, reads data in a row-wise layout that resembles a text table and does not support cross-column references within the same call.
List columns
If any cell in tribble contains a vector longer than one element, that column becomes a list column (type <list>):
tribble(
~label, ~values,
"first", 1:3,
"second", 4:6
)
# # A tibble: 2 × 2
# label values
# <chr> <list>
# 1 first <int [3]>
# 2 second <int [3]>
List columns are useful for storing ragged or hierarchical data. Access individual elements with purrr::map() or dplyr::pull() followed by indexing.
Type coercion
tribble() infers column types from the data you provide, the same way tibble() does. Characters stay character, numbers stay numeric. If you need a specific type, for example, storing a date string as a Date object, use dplyr::mutate() with across() after creation:
tribble(
~name, ~joined, ~score,
"Alice", "2020-01-15", "88",
"Bob", "2019-07-22", "72"
) |>
dplyr::mutate(
dplyr::across(joined, as.Date),
dplyr::across(score, as.integer)
)
# # A tibble: 2 × 3
# name joined score
# <chr> <date> <int>
# 1 Alice 2020-01-15 88
# 2 Bob 2019-07-22 72
tribble() is designed for small, hand-typed datasets, test fixtures, lookup tables, configuration data. The column-formula syntax makes it easy to read and diff in version control compared to a data.frame() call with parallel vectors. However, tribble() scales poorly for more than a dozen rows: the alternating row pattern becomes hard to scan, and there is no syntax for naming the column types. For larger static datasets, consider reading from a CSV literal with readr::read_csv() and a here-string, which gives you explicit types and is more familiar to collaborators.
Column types in tribble() are inferred from the first non-NA value in each column. All values in a column must be coercible to that type; a 1L mixed with 1.5 promotes to double. If you need a specific type that differs from the inferred type (e.g., a column of all-NA that should be logical), use as_tibble() with explicit type arguments or add a mutate() step after tribble().
See also
filter(), filter rows of a tibble by conditionpivot_longer(), reshape data from wide to long formatrownames()— get or set row names of a data frame or tibble