1

我无法在 R 中导入这些数据,因为它不是标准的 csv 格式。我的原始数据如下所示:

BC000068032198109TMAX  232  Q  220  Q  220  Q  244  Q  239  Q  246  Q  270  Q  300  Q  327  Q  279  Q  256  Q  260  Q  289  Q  342  Q  357  Q  359  Q  370  Q  373  Q  367  Q  370  Q  372  Q  357  Q  366  Q  365  Q  355  Q  355  Q  364  Q  343  Q  364  Q  362  Q-9999  
BC000068032198110TMIN  180  Q  170  I  150  I  130  I  150  I  130  I  160  I  190  I  190  I  185  Q-9999     130  I  130  I  160  I  170  I  140  I  160  I  160  I  160  I  160  I  160  I-9999     190  I  180  I  160  I  165  Q  210  I  180  I-9999     190  I  170  I

所以,基本上每行的前 11 个字符是位置的 ID,接下来的 4 个是年份,接下来的 2 个是月份,然后还有 4 个是变量的名称。最后,有 31 个数字是该特定月份和变量的每日测量值。-9999 表示不可用。通常每次测量后都有一个标志(例如“Q”或“I”),但 NA 不是。我对导入这些标志不感兴趣。最终,我希望拥有一个长数据集,其中每个日常测量都与其日期、位置和变量名称相结合。谢谢您的支持。

4

2 回答 2

2

你有一个固定宽度的文件。用于读取此类的基本 R 函数是read.fwf,尽管该readr包添加了几种替代方法来输入可能很方便的列宽,具体取决于您对文件的了解。在这种情况下,您所知道的与基本版本配合得很好:

x <- 'BC000068032198109TMAX  232  Q  220  Q  220  Q  244  Q  239  Q  246  Q  270  Q  300  Q  327  Q  279  Q  256  Q  260  Q  289  Q  342  Q  357  Q  359  Q  370  Q  373  Q  367  Q  370  Q  372  Q  357  Q  366  Q  365  Q  355  Q  355  Q  364  Q  343  Q  364  Q  362  Q-9999  
BC000068032198110TMIN  180  Q  170  I  150  I  130  I  150  I  130  I  160  I  190  I  190  I  185  Q-9999     130  I  130  I  160  I  170  I  140  I  160  I  160  I  160  I  160  I  160  I-9999     190  I  180  I  160  I  165  Q  210  I  180  I-9999     190  I  170  I'

df <- read.fwf(textConnection(x),    # put the path to your file here
               widths = c(11, 4, 2, 4, rep(c(5, 3), 31)),    # a vector of widths
               na.strings = c('-9999', '   ', '  '))    # set your NA values

df
#>            V1   V2 V3   V4  V5  V6  V7  V8  V9 V10 V11 V12 V13 V14 V15 V16
#> 1 BC000068032 1981  9 TMAX 232   Q 220   Q 220   Q 244   Q 239   Q 246   Q
#> 2 BC000068032 1981 10 TMIN 180   Q 170   I 150   I 130   I 150   I 130   I
#>   V17 V18 V19 V20 V21 V22 V23 V24 V25  V26 V27 V28 V29 V30 V31 V32 V33 V34
#> 1 270   Q 300   Q 327   Q 279   Q 256    Q 260   Q 289   Q 342   Q 357   Q
#> 2 160   I 190   I 190   I 185   Q  NA <NA> 130   I 130   I 160   I 170   I
#>   V35 V36 V37 V38 V39 V40 V41 V42 V43 V44 V45 V46 V47  V48 V49 V50 V51 V52
#> 1 359   Q 370   Q 373   Q 367   Q 370   Q 372   Q 357    Q 366   Q 365   Q
#> 2 140   I 160   I 160   I 160   I 160   I 160   I  NA <NA> 190   I 180   I
#>   V53 V54 V55 V56 V57 V58 V59 V60 V61  V62 V63 V64 V65  V66
#> 1 355   Q 355   Q 364   Q 343   Q 364    Q 362   Q  NA <NA>
#> 2 160   I 165   Q 210   I 180   I  NA <NA> 190   I 170    I

事后通过通常的方式重命名并重塑为长格式。

于 2016-12-24T22:10:35.897 回答
1

如果它不是固定宽度的格式,例如:

library(purrr)
library(dplyr)
library(stringi)

lines <- "BC000068032198109TMAX  232  Q  220  Q  220  Q  244  Q  239  Q  246  Q  270  Q  300  Q  327  Q  279  Q  256  Q  260  Q  289  Q  342  Q  357  Q  359  Q  370  Q  373  Q  367  Q  370  Q  372  Q  357  Q  366  Q  365  Q  355  Q  355  Q  364  Q  343  Q  364  Q  362  Q-9999  \nBC000068032198110TMIN  180  Q  170  I  150  I  130  I  150  I  130  I  160  I  190  I  190  I  185  Q-9999     130  I  130  I  160  I  170  I  140  I  160  I  160  I  160  I  160  I  160  I-9999     190  I  180  I  160  I  165  Q  210  I  180  I-9999     190  I  170  I"

readLines(textConnection(lines)) %>%
  map_df(function(x) {

    substr(x, 21, nchar(x)) %>%                   # focus on the part of the line with the readings
      stri_match_all_regex("([-[:digit:]]+)") %>% # pull out all the readings by extracting the #'s
      map(~.[,2]) %>%
      flatten_chr() %>%
      map(~ifelse(. == "-9999", NA, .)) %>%       # make -9999 into NA
      as.numeric() -> value                       # make it a number

    data_frame(
      location_id = substr(x, 1, 11),
      date = as.Date(sprintf("%s-%s-%02d", substr(x, 12, 12+3), substr(x, 16, 16+1), 1:length(value))),
      variable = substr(x, 18, 18+3),
      value = value
    ) %>% filter(!is.na(date)) # don't include invalid dates

  })
## # A tibble: 61 × 4
##    location_id       date variable value
##          <chr>     <date>    <chr> <dbl>
## 1  BC000068032 1981-09-01     TMAX   232
## 2  BC000068032 1981-09-02     TMAX   220
## 3  BC000068032 1981-09-03     TMAX   220
## 4  BC000068032 1981-09-04     TMAX   244
## 5  BC000068032 1981-09-05     TMAX   239
## 6  BC000068032 1981-09-06     TMAX   246
## 7  BC000068032 1981-09-07     TMAX   270
## 8  BC000068032 1981-09-08     TMAX   300
## 9  BC000068032 1981-09-09     TMAX   327
## 10 BC000068032 1981-09-10     TMAX   279
## # ... with 51 more rows

应该管用。

于 2016-12-24T21:47:54.637 回答