【问题标题】:R: read fwf file with missing final columnR:读取缺少最后一列的 fwf 文件
【发布时间】:2020-01-07 21:08:54
【问题描述】:

我正在尝试使用readrread_fwf 解析固定宽度的.txt 文件。大约有 150 万个观测值和大约 150 万个观测值。其中 550 个缺少 60 个变量中的最后 25 个。这种遗漏会导致对这些观察结果所具有的最终变量(下例中的“描述”)的不完美解析,并使数据框没有这些部分填充的列。

例如,

df_baseline <- read_fwf(file = file, fwf_widths(fwf_widths, fwf_names), 
                         col_types = col_types, trim_ws = T) %>% 
   mutate_all(na_if, "")
Warning: 1148 parsing failures.
row         col   expected     actual file
300495 description 240 chars  102        '/path/to/my/file/filename.txt'
300495 NA          59 columns 31 columns '/path/to/my/file/filename.txt' 
500245 description 240 chars  56         '/path/to/my/file/filename.txt' 
500245 NA          59 columns 31 columns '/path/to/my/file/filename.txt' 
500333 description 240 chars  33         '/path/to/my/file/filename.txt' 
See problems(...) for more details.

col_types 是一串由 60 个 'c' 符号组成的字符串,因此所有列都作为字符读入。 fwf_widthsfwf_names 是建议的列宽和列标题的适当规范。

我了解,在 df 的最后一列中缺少值,我违反了文档的“固定宽度”性质。

有没有办法可以 1) 获取 read_fwf 以保留这些部分填充的行? 2)如果不是,我怎么能读到这个txt文件,因为99%的文件都可以按照正常的FWF解析?

【问题讨论】:

  • 如果您包含一个简单的reproducible example 以及可用于测试和验证可能的解决方案的示例输入,则更容易为您提供帮助。

标签: r parsing readr read.fwf


【解决方案1】:

您可以使用data.table::fread()。它会自动检测固定宽度格式,并使用选项 fill=TRUE 应该给你你想要的:

#abc.txt
#a   b   c   d
#1   2   3   4
#1   2   3   4
#2   3
#1   4   3   2
library(data.table)
fread('abc.txt',fill = T)
#    a b  c  d
# 1: 1 2  3  4
# 2: 1 2  3  4
# 3: 2 3 NA NA
# 4: 1 4  3  2

【讨论】:

  • 谢谢,这真的很有帮助。但是,我仍然遇到fread 的问题,它错误地假定了列数。我收到错误消息:“在第 399 行提前停止。预期有 45 个字段,但找到了 48 个”,而实际上有 60 个变量。我在fread 文档中找不到可以指定可变宽度的任何地方,是否有空间可以插入?
【解决方案2】:

这个问题模棱两可,因此难以直接或准确回答,但 fwf 文件 ABCD.txt 说明了 OP 可能询问的三种情况:

# ABCD.txt
# 1ABCD
# 2AB
# 3AB D
# 4ABD
# 5ABCD
#

第 1 行和第 5 行没有缺失值,可以毫无问题地解析。

第 2 行和第 3 行(第一个在三个值之后被截断;第二个在第四列中有一个空占位符)也可以由 read_fwf 毫无问题地解析,尽管会有警告(就像 OP 引用的那样)关于第 2 行(和第 4 行,我们在下面处理)中的截断:

widths <- c(1,1,1,1,1)
file <- "ABCD.txt"

abc <- read_fwf(
  file = path,
  fwf_widths(widths),
  col_types = "ccccc"
  )

abc

输出:

Warning: 3 parsing failures.
row col  expected    actual       file
  2  X4 1 chars   0         'ABCD.txt'
  2  -- 5 columns 4 columns 'ABCD.txt'
  4  X5 1 chars   0         'ABCD.txt'

# A tibble: 5 x 5
  X1    X2    X3    X4    X5   
  <chr> <chr> <chr> <chr> <chr>
1 1     A     B     C     D    
2 2     A     B     NA    NA   
3 3     A     B     NA    D    
4 4     A     B     D     NA   
5 5     A     B     C     D    

请注意,read_fwf 会使用 NA 填充截断的行以作为缺失值。

read.fwffill = TRUE 也可以使用,但速度较慢且不会引发任何警告:

abc <- read.fwf(
  path,
  widths =  widths,
  colClasses = "character",
  na.strings = c(" ","NA"),
  fill = TRUE
  )

abc

输出:

  V1 V2 V3   V4   V5
1  1  A  B    C    D
2  2  A  B <NA> <NA>
3  3  A  B <NA>    D
4  4  A  B    D <NA>
5  5  A  B    C    D
但是,如果我们知道值 D 应该在第五列中,则

第 4 行 不会被任何一种方法“正确”解析。 (read_fwfread.fwf 无法知道这一点,但严格来说,没有解析错误。)

有多种方法可以处理此问题,但如果问题在整个 fwf 文件中是一致的(例如,在所有此类情况下都缺少 60 个变量中的最后 25 个,如问题中所述),那么一种解决方案是使用dplyr 将不正确放置的D 值从第四列转置到第五列(或在OP 的情况下从第35 列到第60 列):

abc <- abc %>%
  mutate(
    V5 = case_when(
      is.na(V5) & !is.na(V4) ~ V4,
      !is.na(V5) ~ V5
      ),
    V4 = case_when(
      V4!=V5 ~ V4
      )
    )

abc

输出:

  V1 V2 V3   V4   V5
1  1  A  B    C    D
2  2  A  B <NA> <NA>
3  3  A  B <NA>    D
4  4  A  B <NA>    D
5  5  A  B    C    D

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-06
    • 1970-01-01
    • 2017-04-28
    • 2022-01-13
    • 2021-10-21
    • 1970-01-01
    • 2013-08-29
    相关资源
    最近更新 更多