【问题标题】:Limit options for col_type when importing using read_csv使用 read_csv 导入时限制 col_type 的选项
【发布时间】:2022-03-15 00:59:34
【问题描述】:

我正在使用readr::read_csv 导入一系列文件,然后通过 API 更新数据。 read_csv 通常可以很好地猜测列类型,但如果文件的前 1000 行中没有数据,则似乎默认为逻辑。如果我总是使用同一个文件/知道特定文件有哪些列,我可以指定列类型(即使用col_spec= cols( sea_level_pressure_set_1d = col_double(),...),但由于有多个文件,它们并不都有所有列。 具体来说,read_csv似乎默认为logical,导致解析失败。

有没有办法强制 read_csv 遵循列类型的层次结构;将其选项限制为仅说字符、双精度和日期时间;或使用带有未知异常的 .default 设置?使用.default 论证,似乎我需要指定所有异常,当文件具有不同格式的异常时会出现我的问题。
我希望 read_csv 只分配日期时间、数字和字符列。

【问题讨论】:

    标签: r readr column-types


    【解决方案1】:

    我想我找到了您的解决方案,但可能需要您提供更多详细信息才能确认:

    第一步: 您首先要为每个文件获取 col() 输出,您可以手动执行或使用 spec_col() 公式为您自动提取该输出(我将在下面显示)。

    #first create mock dataframe
    
    df1 <- tibble(x=1:3,y=letters[1:3])
    
    df2 <- tibble(a=letters[4:6],b=4:6)
    
    write_csv(df2,file = "df2.csv")
    write_csv(df1,file = "df1.csv")
    
    #create file path to pull in files
    file_path <- list.files(path=".",pattern="df")
    
    #extract out each file's col_type, set the default, and put it into a list
    
    list <- map(file_path,
                ~spec_csv(.x,
                          col_types = cols(.default=col_character())
                          )
                )
    

    这会产生以下输出:

    > list
    [[1]]
    cols(
      x = col_double(),
      y = col_character()
    )
    
    [[2]]
    cols(
      a = col_character(),
      b = col_double()
    )
    

    第二步:分配默认值(可选) 如果你想分配一个默认值,那么你需要使用下面的 for 循环(我不知道如何用 map 做到这一点,但下面的工作)。这基本上利用了cols 类对象的特殊属性,并根据您分配的内容分配默认值。如果您为其分配文字字符值,则默认值将变为字符。如果你给它分配一个文字数值,那么默认值将变成数值。

    #get the length of your list
    x <- seq_along(list)
    #loop through each element of the list and assign the <collect_guess> argument a value
    for(i in x){
    list[[i]][[2]] <- list[[i]][[2]] <- "character"
    }
    

    这会产生以下输出:

    > list
    [[1]]
    cols(
      .default = col_character(),
      x = col_double(),
      y = col_character()
    )
    
    [[2]]
    cols(
      .default = col_character(),
      a = col_character(),
      b = col_double()
    )
    

    第三步: 使用这个存储每个文件的 col() 参数的变量“list”,我们需要创建一个新的 tibble,将 col() 参数与相应的文件配对。我们可以用一个简单的 tibble 来做到这一点。

    col_map<- tibble(x=list,y=file_path)
    
    

    第 4 步 然后使用map2_df 函数,它允许您同时通过两个向量(在本例中为col() 参数(.x)和文件路径(.y)到一个公共函数read_csv

    
    map2_df(.x=col_map$x,
    .y=col_map$y,
    .f = ~read_csv(file=.y,col_types=.x)
    )
    
    

    这应该将您的所有文件保存到一个新的 tibble。

    【讨论】:

    • 谢谢,但我认为这不会改变阅读器的行为。我面临的问题是read_csv 默认为guess_max=1000,如果第一个guess_max 行中没有数据,它将默认为逻辑,并且对于其中任何非0、1、T 的F 数据,解析将失败柱子。 spec_csv 具有相同的行为 - 请参阅 vignette("column-types", package = "readr")。我想我最终增加了guess_max=inf,代价是大大减慢了这个过程。我一直在寻找一种方法来避免产生如此巨大的成本。
    • 提取 col_types 可能会起作用,然后在列表中搜索 col_logical() 并将其替换为 col_character(),这将读取任何数据,然后传递修改后的列表。根据列的实际类型,这可能需要在导入文件后进行一些额外的数据处理。
    • 看起来当前版本的 readr(版本 >= 2.0.0)正在使用不同的方法来猜测列类型(请参见上面的小插图),因此在使用时这可能不是一个问题更新版本。
    • 您好,感谢您的回复,那么也许我误解了原始请求。如果您不希望阅读器自动猜测列类型,您可以使用col() 函数和as.col_spec 手动设置列类型并离线保存。因此,要么让 readr 自动为您生成 col 类型,要么您手动设置它们。这有意义吗?
    • 我确实希望 readr 自动猜测列类型,因为这样可以为大多数列正确分配数字和日期时间类。我正在处理一系列不同的文件,这些文件共享一些列,但有些文件有 12 列,另一些有 35 列,还有一些有 18 列。在某些情况下,一些列只会在错误期间包含数据,通常是文件的一半。我想让读者猜测数据类型,但如果它没有找到任何东西,选择字符而不是逻辑。
    猜你喜欢
    • 2016-04-12
    • 1970-01-01
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    相关资源
    最近更新 更多