【问题标题】:Importing text file into R that has spaces that are not new columns将文本文件导入具有不是新列的空格的 R
【发布时间】:2017-08-03 14:47:07
【问题描述】:

我有一个来自 NOAA 的文本文件,其中有一个气象站列表,应该有 8 列,没有标题。它们都用空格隔开,但在下面的例子中,有些名称像“ABBEVILLE”,有些名称为“ANDALUSIA 3 W”。当我用 read.table 将它读入 R 时,我得到 10 列。

USC00010008 31.5702 -85.2482 139.0 AL ABBEVILLE 15 -6

USC00010252 31.3071 -86.5226 76.2 安达卢西亚 3 W 15 -6

precip_stations <- read.table("hpd-stations.txt", sep = "", header = FALSE, fill = T) 

> V1           V2       V3     V4  V5     V6    V7  V8 V9  V10
>USC00010008 31.5702 -85.2482 139  AL ABBEVILLE 15  -6
>USC00010252 31.3071 -86.5226 76.2 AL ANDALUSIA  3  W  15  -6

有没有办法让它在一列中导入“ANDALUSIA 3 W”之类的内容?我认为 fill = FALSE 可能会起作用,但如果我这样做,我会收到错误消息。

【问题讨论】:

  • 使用readLines 读入并使用正则表达式进行预处理以插入引号。然后传递给read.table。但是,我猜在您开始使用它们之前,这些文件确实是固定宽度格式的文件,并且以这种方式保留它们并使用 read.fwf 会更容易
  • 也有可能是制表符分隔的文件。使用sep = \t 会改变导入吗?
  • \t 将所有内容放在一列中,我没有更改从 NOAA 下载的文件中的任何内容
  • 这里是文件link的链接
  • 看到了吗?它是一个 FWF 文件。请一遍又一遍地阅读我之前的评论,直到它的价值下沉。

标签: r read.table


【解决方案1】:

读取固定宽度格式文件需要您首先识别没有有效的分隔符,然后使用 `read.fwf。这反过来要求您确定间距以计算宽度:

inp <- "
USC00010008  31.5702  -85.2482  139.0 AL ABBEVILLE                                                                                 15    -6
USC00010063  34.2553  -87.1814  249.3 AL ADDISON                                                                                   15    -6"
> cat( paste0( rep( 0:9, 13), collapse=""))
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

请注意,适当的文本编辑器有时可能有助于“标尺”。我有时会用:

cat( paste0( rep( c(1:9,0), 7), collapse="")); cat("\n"); 
cat(paste0( sprintf( "% 10s", 1:7), collapse=""))
#---------------------------------------
#1234567890123456789012345678901234567890123456789012345678901234567890
#         1         2         3         4         5         6         7

事实上,我刚刚意识到我应该创建一个创建可调节标尺的函数:

ruler <- function(len=7){ cat( paste0( rep( c(1:9,0), len), collapse=""))
                          cat("\n")
                          cat(paste0( sprintf( "% 10s", 1:len), collapse="")) }
> ruler(13)  # could not get a proper display of the output in SO

(现在保存到我的 .Rprofile 实用函数套件中。)

然后猜测宽度并在此错误后进行一些调整:

> read.fwf(textConnection(inp), widths=c(10, 10,10, 7, 90, 5, 5) )
          V1         V2       V3    V4                                                                                         V5 V6 V7
1       <NA>       <NA>       NA    NA                                                                                       <NA> NA NA
2 USC0001000 8  31.5702 -85.2482 139.0  AL ABBEVILLE                                                                               1  5
3 USC0001006 3  34.2553 -87.1814 249.3  AL ADDISON                                                                                 1  5

我终于明白了:

 myfwf <- readLines("ftp://ftp.ncdc.noaa.gov/pub/data/hpd/auto/v1/beta/hpd-stations.txt" )
> mytbl <- read.fwf(textConnection(myfwf[1:12]), widths=c(11, 10,10, 7, 89, 5, 5) )
> mytbl
            V1      V2       V3    V4                                                                                        V5 V6 V7
1  USC00010008 31.5702 -85.2482 139.0 AL ABBEVILLE                                                                               1  5
2  USC00010063 34.2553 -87.1814 249.3 AL ADDISON                                                                                 1  5
3  USC00010140 32.2322 -87.4104  53.3 AL ALBERTA                                                                                 1  5
4  USC00010252 31.3071 -86.5226  76.2 AL ANDALUSIA 3 W                                                                           1  5
5  USC00010369 33.2941 -85.7788 311.5 AL ASHLAND 3 ENE                                                                           1  5
6  USC00010390 34.7752 -86.9508 210.0 AL ATHENS                                                                                  1  5
7  USC00010402 31.1820 -87.4390  91.4 AL ATMORE                                                                                  1  5
8  USC00010425 32.5992 -85.4653 166.1 AL AUBURN NO.2                                                                             1  5
9  USC00010748 33.6972 -87.6491 157.9 AL BERRY 3 NW                                                                              1  5
10 USC00010957 34.2008 -86.1633 326.1 AL BOAZ                                                                                    1  5
11 USC00011099 34.9786 -85.8008 204.2 AL BRIDGEPORT 5 NW                                                                         1  5
12 USC00012124 32.8622 -85.7358 223.4 AL DADEVILLE 2                                                                             1  5

请注意,我将其限制在前 12 行,因为第 13 行有一个 octothorpe(“#”),这会导致行过早终止,因为那是 R 注释字符。

USC00012172  30.2505  -88.0775    2.4 AL DAUPHIN ISLAND #2                                                                         15    -6

所以需要comment.char="":

> mytbl <- read.fwf(textConnection(myfwf), widths=c(11, 10,10, 7, 89, 5, 5) , comment.char="")
> str(mytbl)
'data.frame':   1920 obs. of  7 variables:
 $ V1: Factor w/ 1920 levels "CQC00914080",..: 23 24 25 26 27 28 29 30 31 32 ...
 $ V2: num  31.6 34.3 32.2 31.3 33.3 ...
 $ V3: num  -85.2 -87.2 -87.4 -86.5 -85.8 ...
 $ V4: num  139 249.3 53.3 76.2 311.5 ...
 $ V5: Factor w/ 1920 levels "AK CENTRAL NO 2                                                                          ",..: 8 9 10 11 12 13 14 15 16 17 ...
 $ V6: Factor w/ 9 levels "    1","0   1",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ V7: Factor w/ 2 levels "5    ","5   -": 1 1 1 1 1 1 1 1 1 1 ...

【讨论】:

  • 做得很好。之后您可以添加mytbl$V5 &lt;- trimws(mytbl$V5) 以删除V5 中的空白。
【解决方案2】:

丑陋,但有效:

x <- readLines("hpd-stations.txt")

l <- list()

for (i in 1:length(x)) {
  a <- strsplit(x[i], " ")
  b <- t(sapply(a, "[", 1:5))
  c <- length(a[[1]]) - 5 - 2
  d <- t(sapply(a, "[", 6:(5+c)))
  e <- t(sapply(a, "[", (5+c+1):length(a[[1]])))
  res <- as.data.frame(cbind(b, paste0(d, collapse = " "), e))
  l[[i]] <- res
}

data <- dplyr::bind_rows(l)

给你

> data
           V1      V2       V3  V4 V5              V6 V7 V8
1 USC00010008 31.5702 -85.2482 139 AL       ABBEVILLE 15 -6
2 USC00010009 31.5602 -85.2482 179 AL ABBEVILLFOO 3 W 15 -6

使用虚拟数据进行测试。

编辑:刚刚看到文件的链接出现了。尚未对此进行测试,但您现在应该考虑使用read.fwf()

【讨论】:

  • @Jeffkrop:快到了。看到需要禁止默认注释字符。
猜你喜欢
  • 1970-01-01
  • 2021-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 2010-09-14
  • 1970-01-01
  • 2017-03-09
相关资源
最近更新 更多