无法使用 readr 阻止因子列中空单元格的 NA

can't prevent NAs for empty cells in factor columns using readr

我正在尝试读取包含一些空单元格的文件并获取预期的空单元格 NA。 我有一些特殊的列,它们的值只能是 '''+'。所以我想通过使用

将这些列设置为因子 class
read_tsv('file.txt', 
         col_types=list(
             column_with_empty_cells=col_factor(c('','+'))))

但该列在这些列中仍然有 NAs。我可以通过更改 na 参数来更改 readr_tsv 函数的全局行为,但这不是我想要的。我只想在特定列中更改它。

有没有办法把这些NAs直接转换成''?之后我肯定可以这样做,但我想知道我是否以错误的方式使用了这个东西。

编辑 这是一个test file

我如何实际上传文件?我只能附上图片...

根据 readr 的文档,没有为列的子集传递多个 na 参数的实现,只有一个全局规范。我认为这在需要计算效率时最为突出。对于这些情况,可能值得多次调用 read_tsv 指定要使用 na 参数规范读取的列的子集并跳过所有其他列。然后对具有不同 na 参数的列的其他子集重复该过程,并只读取应使用该 na 参数解析的列。最后,可以 cbind 多个数据帧。

尚未向 readr 开发人员提出此问题。如果您希望将其作为增强功能提交,请随时通过在项目存储库中生成一个新问题来提交:Readr.

您可以使用 lapplyfactor 创建一个新函数来解决此问题:

library(readr)

read_tsv2 <- function(file, na.char=" "){
  test <- read_tsv(file = file, col_types=list(column_with_empty_cells=col_character()))
  test <- as.data.frame(test)
  names_tsv <- names(test)
  test <- lapply(test,
         function(x){
    if(sum(is.na(x))!=length(x)){
      x[is.na(x)] <- na.char 
    factor(x,levels = unique(x))
    }else{
      x
    }
  }
  )
  test <- do.call(cbind.data.frame, test)
  names(test) <- names_tsv
  test
}

file <- read_tsv2(file = "~/Downloads/file.txt", na.char = " ")

file

   test column_with_empty_cells
1  <NA>                        
2  <NA>                        
3  <NA>                        
4  <NA>                        
5  <NA>                        
6  <NA>                        
7  <NA>                        
8  <NA>                        
9  <NA>                        
10 <NA>                        
11 <NA>                        
12 <NA>                        
13 <NA>                        
14 <NA>                        
15 <NA>                        
16 <NA>                        
17 <NA>                        
18 <NA>                        
19 <NA>                        
20 <NA>                        
21 <NA>                        
22 <NA>                        
23 <NA>                        
24 <NA>                       +
25 <NA>                       +
26 <NA>                        
27 <NA>                        
28 <NA>                       +

read_tsvread_delim 的自定义实现,read_csv 也是如此。 tsv 专门用于读取制表符分隔的文件,在本例中也是您的测试文件。如果您不依赖于使用特定的制表符分隔实现,则可以使用 read_csv 轻松解决您的问题。

read_csv 如果在列中发现很少的唯一字符集,默认情况下会将 class 作为因素。

获取值作为因子

read.csv("test.txt", sep = "\t")  

获取值作为字符

read.csv("test.txt", sep = "\t", stringsAsFactors = FALSE)

Sample dataframe read

编辑 1

如果您希望将具有 " " 的特定列视为 NA,您可以在阅读时仅使用 lappy 将 class 传递给那些列列表,但是基于关于你的问题,看起来你希望 NULL 被视为 NA 并且不应强制任何其他字符。