根据现有数据框为read_csv创建col_types字符串规范

mpe*_*tis 5 r readr

我有一个脚本中的data.frame或tibble,它们被写入CSV文件。在另一个脚本中,该相同的CSV文件被读取到data.frame或tibble中。通过使用read_csv()带有col_types=参数的,我可以指定要读取的列类型。这是一个示例:

# Create an example dataframe
df <- tibble::tibble(a=1L
                     , b=1.0
                     , c="a"
                     , d=TRUE
                     , e=lubridate::ymd_hms("2019-03-19T13:15:18Z")
                     , f=lubridate::ymd("2019-03-19")
                     , g=factor("a"))

# Write csv to file
readr::write_csv(df, "temp.csv")

# read it back in, supplying a col_types string spec
readr::read_csv("temp.csv", col_types="idclTDf")
#> # A tibble: 1 x 7
#>       a     b c     d     e                   f          g    
#>   <int> <dbl> <chr> <lgl> <dttm>              <date>     <fct>
#> 1     1     1 a     TRUE  2019-03-19 13:15:18 2019-03-19 a
Run Code Online (Sandbox Code Playgroud)

reprex软件包(v0.2.1)创建于2019-03-19

问题是我需要知道col_types=函数上的参数read_csv()(或者让我猜,这是我不想做的)。我想要一种获取原始文件的方法df,然后在将其写出之前,col_typesdf对象生成字符串,该对象可用于读回转储的CSV。也就是说,我想要一些东西来创建"idclTDf"给定的字符串data.frame作为参数。

我看到这里有一个功能请求(我已经加了两美分):https : //github.com/tidyverse/readr/issues/895

mpe*_*tis 6

我确实有一个解决方案,它有效,但我认为它非常不完整且没有强化。这是我对解决方案的尝试。

# https://github.com/tidyverse/readr/issues/895
# Create function to take a tibble and return a character string that can be used in `readr::read_csv()`
# as the `col_types` argument to re-read this back into a dataframe after it had been written out
# by `write_csv()`.

get_col_types_short <- function(.df) {
    # Get column classes from input dataframe
    lst_col_classes__ <- purrr::map(.df, ~ class(.x))

    # Map classes to known single-character col_types indicator
    vl_col_class_char__ <- purrr::map_chr(lst_col_classes__, function(.e) {
        dplyr::case_when(
              "logical" %in% .e   ~ "l"
            , "integer" %in% .e   ~ "i"
            , "numeric" %in% .e   ~ "d"
            , "double" %in% .e    ~ "d"
            , "character" %in% .e ~ "c"
            , "factor" %in% .e    ~ "f"
            , "Date" %in% .e      ~ "D"
            , "POSIXct" %in% .e   ~ "T"
            , TRUE                ~ "c"
        )
    })

    # Return vector of single-character col_type indicator.
    # Element name is the source column it came from.
    vl_col_class_char__
}

# Test it:
df <- tibble::tibble(a=1L
                     , b=1.0
                     , c="a"
                     , d=TRUE
                     , e=lubridate::ymd_hms("2019-03-19T13:15:18Z")
                     , f=lubridate::ymd("2019-03-19")
                     , g=factor("a"))

v__ <- get_col_types_short(df)

# Show what is actually returned
v__
#>   a   b   c   d   e   f   g 
#> "i" "d" "c" "l" "T" "D" "f"

# Collapse it to show how to use it
paste(v__, collapse="")
#> [1] "idclTDf"


# Write csv to file
readr::write_csv(df, "temp.csv")

# read it back in, using the above col_types string spec
readr::read_csv("temp.csv", col_types=paste(v__, collapse=""))
#> # A tibble: 1 x 7
#>       a     b c     d     e                   f          g    
#>   <int> <dbl> <chr> <lgl> <dttm>              <date>     <fct>
#> 1     1     1 a     TRUE  2019-03-19 13:15:18 2019-03-19 a
Run Code Online (Sandbox Code Playgroud)

reprex 包(v0.2.1)于 2019 年 3 月 19 日创建

  • 我们会,我不确定我是否涵盖了日期和日期时间的所有可能的变体类型,我没有错误处理,最好有一个非短函数返回引用的调用,例如“col_character()”等. 我认为这是一个可用的开始,还没有测试边缘情况。我怀疑我是第一个遇到这个问题的人,可能会有更好、更强大的解决方案。 (2认同)
  • 最近似乎已经在 [readr](https://github.com/tidyverse/readr/issues/895) 中使用新函数 `as.col_type()` 解决了这个问题。 (2认同)
  • @hplieninger,我认为这应该是“as.col_spec()”,对吧?当前(1.3.1)版本的“readr”中没有“as.col_type()”。 (2认同)