59

I have a vector of column names called tbl_colnames.

I would like to create a tibble with 0 rows and length(tbl_colnames) columns.

The best way I've found of doing this is...

tbl <- as_tibble(data.frame(matrix(nrow=0,ncol=length(tbl_colnames)))

and then I want to name the columns so...

colnames(tbl) <- tbl_colnames.

My question: Is there a more elegant way of doing this?

something like tbl <- tibble(colnames=tbl_colnames)

colorlace
  • 816
  • 2
  • 10
  • 17
  • 2
    tibble columns have data types. Are you trying to make all your columns number? Also, what do you plan to do with this empty tibble? You're not going to try to add rows to it, are you? Because that's very inefficient. Better to build your data by columns first. Some more context here would be helpful. – MrFlick Feb 16 '18 at 19:47
  • 1
    You don't need to wrap with data.frame. Just `as_tibble(matrix(.` – akrun Feb 16 '18 at 19:50
  • Well I have a list of 5 lists and I want to rowbind them all together into one tibble. The idea was to start with an empty tibble and loop through the list rowbinding them to the initialized tibble one-by-one. – colorlace Feb 20 '18 at 15:08

6 Answers6

53
my_tibble <- tibble(
  var_name_1 = numeric(),
  var_name_2 = numeric(),
  var_name_3 = numeric(),
  var_name_4 = numeric(),
  var_name_5 = numeric()
)

Haven't tried, but I guess it works too if instead of initiating numeric vectors of length 0 you do it with other classes (for example, character()).

This SO question explains how to do it with other R libraries.

According to this tidyverse issue, this won't be a feature for tribbles.

Daniel
  • 1,005
  • 1
  • 16
  • 22
  • 1
    Thanks. I was hoping to use the `tbl_colnames` vector directly when I asked this question, but it's true that this is one way to do it (if a bit cumbersome). In any case, it could be helpful for others seeking different ways to init tibbles. – colorlace Sep 03 '19 at 14:09
  • I like this answer because it is explicit. You can tell at a glance that you are creating an empty table with specific column names and data types. – Andrew Brēza Aug 09 '22 at 15:40
35

Since you want to combine a list of tibbles. You can just assign NULL to the variable and then bind_rows with other tibbles.

res = NULL
for(i in tibbleList)
   res = bind_rows(res,i)

However, a much efficient way to do this is

bind_rows(tibbleList) # combine all tibbles in the list
Tony416
  • 596
  • 6
  • 11
  • 1
    Thank you for your answer. It was a list of lists (not a list of tibbles), but this seems to work anyway! – colorlace Jun 06 '18 at 15:51
  • 5
    This answer is responsive to a comment that is only peripherally related the title of and question posted on this page. – Aren Cambre Oct 31 '19 at 02:38
  • @ArenCambre I'm thankful for it. I am visiting this page as someone relatively new to R, and seeing a better way of doing things in R seems very relevant. The question asked was the same as I had, but it turns out there is a better way. – David Nov 23 '22 at 09:06
  • @David that's fine. I just wanted to be clear that this does not answer the question. While it may have value, this question should be revised or the author should select a different answer as the accepted answer. – Aren Cambre Nov 23 '22 at 19:49
  • @ArenCambre As someone new to R though, this is the question I asked, and it was the wrong question. However, without someone answering this question, and then me seeing it, I would not have realized I was asking the wrong question. There is no need to create an empty tibble, nor is it the most performant/Tidy way of doing things. It's like the many answers out there proposing more Pythonic solution to Python questions which have subtly wrong assumptions built-in to the question being asked. They are still highly contextually relevant to the question being asked. – David Nov 26 '22 at 00:59
24

For anyone still interested in an elegant way to create a 0-row tibble with column names given by a character vector tbl_colnames:

tbl_colnames %>% purrr::map_dfc(setNames, object = list(logical()))

or:

tbl_colnames %>% purrr::map_dfc(~tibble::tibble(!!.x := logical()))

or:

tbl_colnames %>% rlang::rep_named(list(logical())) %>% tibble::as_tibble()

This, of course, results in each column being of type logical.

Nik
  • 355
  • 2
  • 6
9

The following command will create a tibble with 0 row and variables (columns) named with the contents of tbl_colnames

tbl <- tibble::tibble(!!!tbl_colnames, .rows = 0, .name_repair = ~ tbl_colnames)
R Moore
  • 151
  • 2
  • 4
  • When I try this I get weirdly quoted column names. colnames(tbl) prints "\"var_name_1\"" "\"var_name_2\"" etc... – mandmeier May 11 '23 at 22:40
  • In my case the function call added double quotes. I removed those quotes with the argument .name_repair: `.name_repair = \(x) str_remove_all(x, '"')` – dzegpi May 16 '23 at 18:05
7

You could abuse readr::read_csv, which allow to read from string. You can control names and types, e.g.:

tbl_colnames <- c("one", "two", "three", "c4", "c5", "last")
read_csv("\n", col_names = tbl_colnames) # all character type
read_csv("\n", col_names = tbl_colnames, col_types = "lcniDT") # various types
Marek
  • 49,472
  • 15
  • 99
  • 121
7

I'm a bit late to the party, but for future readers:

as_tibble(matrix(nrow = 0, ncol = length(tbl_colnames)), .name_repair = ~ tbl_colnames)

.name_repair allows you to name you columns within the same function.

Daniël
  • 71
  • 1
  • 3