readr: Creating cols() object from a string.

Hi,

I need to read several different data inputs with read_csv(). I have somewhere saved the column types, which I want to use to check errors. My question is: how do I turn a string with columns types into a cols() object.

For example, this works:

    cols('c', 'n')

But I need something like this:

    aa <- c('c','n')
    cols(aa)

This second call gives me an error:

> aa <- c('c','n')
> cols(aa)
Error in switch(x, _ = , - = col_skip(), ? = col_guess(), c = col_character(), : EXPR must be a length 1 vector

Hi @leobarlach! Welcome!

(updating my answer because sometimes you forget obvious things! :woman_facepalming:)

The the col_types parameter (to any of the read_delim() variants) is more flexible than calling cols() directly, and is probably what you're going to actually use in practice. It takes either a list (ideally named) of string shorthand references, or a single string, so you'll need to as.list() your vector or str_flatten() / paste0() the strings together:

library(tidyverse)

aa <- c('c','n')

spec_csv(
  "chr1,num1
  a,1
  b,2",
  col_types = as.list(aa)
)
#> cols(
#>   chr1 = col_character(),
#>   num1 = col_number()
#> )

spec_csv(
  "chr1,num1
  a,1
  b,2",
  col_types = str_flatten(aa)
)
#> cols(
#>   chr1 = col_character(),
#>   num1 = col_number()
#> )

spec_csv(
  "chr1,num1
  a,1
  b,2",
  col_types = paste0(aa, collapse = "")
)
#> cols(
#>   chr1 = col_character(),
#>   num1 = col_number()
#> )

Created on 2018-11-19 by the reprex package (v0.2.1)

3 Likes
aa <- c('c','n')
do.call(readr::cols, as.list(aa))

Also works! :smile: But are there any scenarios where this works and plain ol' as.list(aa) doesn't work? I'm having trouble thinking of any.

This is exactly what is done if you provide col_types with list argument in readr function.

aa <- c('c','n')

spec_csv(
  "chr1,num1
  a,1
  b,2",
  col_types = as.list(aa)
)

will call internally

readr:::as.col_spec.list(as.list(aa))

and

readr:::as.col_spec.list <- function (x) {
    do.call(cols, x)
}

So I think this is pretty equivalent. @jcblum I think of no use case either.

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.