Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

readr - how to update col_spec object from spec()

Tags:

r

readr

I like the workflow regarding column specs as described in this RStudio blog post. Basically, one can grab the column specification after a read_csv import, and then save that down for use later. For example, from that post:

mtcars2 <- read_csv(readr_example("mtcars.csv"))
#> Parsed with column specification:
#> cols(
#>   mpg = col_double(),
#>   cyl = col_integer(),
#>   disp = col_double(),
#>   hp = col_integer(),
#>   drat = col_double(),
#>   wt = col_double(),
#>   qsec = col_double(),
#>   vs = col_integer(),
#>   am = col_integer(),
#>   gear = col_integer(),
#>   carb = col_integer()
#> )
# Once you've figured out the correct types
mtcars_spec <- write_rds(spec(mtcars2), "mtcars2-spec.rds")

# Every subsequent load
mtcars2 <- read_csv(
  readr_example("mtcars.csv"), 
  col_types = read_rds("mtcars2-spec.rds")
)

Unfortunately, the spec objects themselves are lists with attributes, but those don't match the different column specifications as provided to the read_csv function via the col_types parameter

> mtcars_spec$cols$cyl
<collector_integer>
> str(mtcars_spec$cols$cyl)
 list()
 - attr(*, "class")= chr [1:2] "collector_integer" "collector"
> class(mtcars_spec)
[1] "col_spec"

Also, the .rds files are ugly for editing in Windows (at least for me).

I'd like to be able to edit a large col_spec object (say, to skip certain columns, or otherwise edit the class). I can keep guessing at the strings I'd need to edit the list, like so:

attr(mtcars_spec$cols$cyl,"class")[1] = "collector_skip"` # this worked!
> mtcars_spec
cols(
  mpg = col_double(),
  cyl = col_skip(),
  disp = col_double(),
  hp = col_integer(),
  drat = col_double(),
  wt = col_double(),
  qsec = col_double(),
  vs = col_integer(),
  am = col_integer(),
  gear = col_integer(),
  carb = col_integer()
)

But that seems awkward. Is there a more elegant way to update the column classifications, say, as in my example, to try to skip the mtcars$cyl column? Or, if not an elegant way, a way that covers all the possible types? I don't want to do lots of guessing about how I'd implement <collector_date> with various date formats.

like image 300
Rafael Zayas Avatar asked Aug 25 '16 00:08

Rafael Zayas


1 Answers

Here is a minimal version of Jim Hester's Github post

library(readr)
test_spec <- spec_csv('x,y,theDate,skipCol
  1,a,"21/01/2018", "skip1
  2,z,"31/01/2018", "skip2')

test_spec
#> cols(
#>   x = col_integer(),
#>   y = col_character(),
#>   theDate = col_character(),
#>   skipCol = col_character()
#> )

test_spec$cols[["theDate"]] <- col_date("%d/%m/%Y")
test_spec$cols[["skipCol"]] <- col_skip()

test_spec
#> cols(
#>   x = col_integer(),
#>   y = col_character(),
#>   theDate = col_date(format = "%d/%m/%Y"),
#>   skipCol = col_skip()
#> )

Notes

  • You need to know the date format of your data.
  • You can use readr::spec_csv() on a file
like image 145
Greg H Avatar answered Oct 05 '22 02:10

Greg H