【问题标题】:Creating data frame with dates and data from a text files使用文本文件中的日期和数据创建数据框
【发布时间】:2016-06-23 02:13:37
【问题描述】:

我想从一个文件创建一个数据框。首先,我从互联网将ftp 文件下载到我的电脑中。文件可在此链接中找到:data from ftp。我想在一个列上创建一个带有日期的数据框(取自每个文件的Launch date 行),并在其他列上创建一个数据。
为了抓取所有文件,我使用了以下代码:

`setwd("C:/Users/")
path = "~C:/Users/"
files <- lapply(list.files(pattern = '\\.l100'), readLines) 
test.sample<-do.call(rbind, lapply(files, function(lines){
  # for each file, return a data.frame of the datetime, pulled with regex
  data.frame(datetime = lubridate::dmy(sub('^.*Launch Date*    : ', '', lines[6])),
             # and the data, read in as text
             read.table(text = lines[13:length(lines)]))
}))`

我想知道上面的代码有什么问题。如果您可以编写新代码也很棒。提前谢谢你。

数据如下:

National Oceanic and Atmospheric Administration, U.S. Department of Commerce
Station        : Pago Pago, American Samoa
Station Height : 5 meters
Latitude       : -14.33
Longitude      : -170.71
Flight Number  : ASA016
Launch Date    : 18 July 1986
Launch Time    : 02:31:00 GMT
Radiosonde Type: 
Radiosonde Num : 
O3 Sonde ID    : 4A1834   Background: 0.050 microamps (0.20 mPa)  Flowrate: 29.90 sec/100ml  RH Corr: 2.00 %
Sonde Total O3 : 268   (51) DU      Sonde Total O3 (SBUV): 251 (35) DU

Level   Press    Alt   Pottp   Temp   FtempV   Hum  Ozone  Ozone   Ozone  Ptemp  O3 # DN O3 Res
 Num     hPa      km     K      C       C       %    mPa    ppmv   atmcm    C   10^11/cc   DU
   0  1007.7   0.005   304.0   31.5    26.0     73   1.63  0.016  0.0000   38.4    3.883    268
   1  9999.9   0.100  9999.9  999.9   999.9    999  99.90 99.999 99.9990  999.9  999.999   9999
   2   982.0   0.200   301.2   26.5    21.4     74   1.69  0.017  0.0003   38.4    4.096    267
   3  9999.9   0.300  9999.9  999.9   999.9    999  99.90 99.999 99.9990  999.9  999.999   9999
   4   960.0   0.400   301.2   24.6    20.6     79   1.64  0.017  0.0006   38.4    3.983    267
   5  9999.9   0.500  9999.9  999.9   999.9    999  99.90 99.999 99.9990  999.9  999.999   9999
   6   946.0   0.600   301.1   23.2    20.2     83   1.65  0.017  0.0008   38.4    4.021    267
   7   932.0   0.700   300.9   21.8    19.9     89   1.65  0.018  0.0010   38.5    4.040    267
   8   920.9   0.800   301.1   21.0    16.4     75   1.65  0.018  0.0012   38.5    4.051    266
   9  9999.9   0.900  9999.9  999.9   999.9    999  99.90 99.999 99.9990  999.9  999.999   9999
  10  9999.9   1.000  9999.9  999.9   999.9    999  99.90 99.999 99.9990  999.9  999.999   9999
  11   893.0   1.100   302.0   19.2    12.1     64   1.58  0.018  0.0016   38.5    3.923    266
  12  9999.9   1.200  9999.9  999.9   999.9    999  99.90 99.999 99.9990  999.9  999.999   9999

我有很多这样的文件。再次感谢。

【问题讨论】:

  • 您的代码几乎没有问题,但我不确定是因为复制/粘贴错误还是代码本身存在问题。例如,您的第一个带有read.table 的代码永远不会完成。然而,你得到的实际错误是什么?你能提供一个文件包含的小样本吗?
  • @r2evans 我做了第一个作为一个简单的试验。但是你可以在问题中提供的链接中找到文件(files)的内容。
  • @alistaire 你怎么看?感谢您上次提供的精彩代码。
  • 问题解决了吗?你得到什么错误?

标签: r dataframe ftp read.table data-extraction


【解决方案1】:

虽然我喜欢这个固定宽度的表格文件中的元数据和一些自文档,但以编程方式导入它们可能会很有趣。 Excel 恰好做得很好,因为它不会抱怨与模式不匹配的行,但这无助于导入大量文件。

所以我们需要一些自制的东西。我只下载了其中两个文件,但这应该同样适用于更多文件。 (我假设格式是一致的,否则我们需要修复一些魔术常量,例如 15(要忽略的行)和 29(包含表头的行)。)

(files <- list.files(pattern = "asa*"))
# [1] "asa001_1986_04_01_20.l100" "asa002_1986_04_14_18.l100"

这是主力。与其“只是”按照您的要求获取日期,不如获取所有元数据标题。他们通过在一些行(以及一些带有空格的标签)上放置倍数来制造一些问题,但我认为我找到了一个合适的模式来找到它们。

alldfs <- lapply(files, function(f) {
  # read in all but the data; two MAGIC CONSTANTS
  txt <- readLines(f, n = 29)[-(1:15)]
  i <- which(! nzchar(trimws(txt)))
  hdrs <- sapply(strsplit(txt[1:(i-1)], ": "), trimws)
  hdrsdf <- as.data.frame(Reduce(c, lapply(hdrs, function(hdr) {
    z <- strsplit(hdr, "  ")
    if (length(z) == 1) {
      setNames(NA_character_, nm = z[[1]])
    } else {
      setNames(lapply(z[-1], head, n=1), nm = trimws(sapply(z[-length(z)], tail, n=1)))
    }
  })), stringsAsFactors = FALSE)
  df <- as.data.frame(lapply(read.table(f, skip=27, stringsAsFactors=F)[-1,],
                             as.numeric))
  cbind.data.frame(hdrsdf, df)
})
length(alldfs)
# [1] 2

结果是一个宽的data.frame。前 13 列是常量,即元数据标题。如果您只想要Launch.Date,请随意放弃其余的。

str(alldfs[[1]])
# 'data.frame': 361 obs. of  27 variables:
#  $ Station              : chr  "Pago Pago, American Samoa" "Pago Pago, American Samoa" "Pago Pago, American Samoa" "Pago Pago, American Samoa" ...
#  $ Station.Height       : chr  "5 meters" "5 meters" "5 meters" "5 meters" ...
#  $ Latitude             : chr  "-14.33" "-14.33" "-14.33" "-14.33" ...
#  $ Longitude            : chr  "-170.71" "-170.71" "-170.71" "-170.71" ...
#  $ Flight.Number        : chr  "ASA001" "ASA001" "ASA001" "ASA001" ...
#  $ Launch.Date          : chr  "01 April 1986" "01 April 1986" "01 April 1986" "01 April 1986" ...
#  $ Launch.Time          : chr  "20:40:00 GMT" "20:40:00 GMT" "20:40:00 GMT" "20:40:00 GMT" ...
#  $ Radiosonde.Type      : chr  NA NA NA NA ...
#  $ Radiosonde.Num       : chr  NA NA NA NA ...
#  $ O3.Sonde.ID          : chr  "4A1911" "4A1911" "4A1911" "4A1911" ...
#  $ Background           : chr  "0.050 microamps (0.19 mPa)" "0.050 microamps (0.19 mPa)" "0.050 microamps (0.19 mPa)" "0.050 microamps (0.19 mPa)" ...
#  $ Flowrate             : chr  "29.10 sec/100ml" "29.10 sec/100ml" "29.10 sec/100ml" "29.10 sec/100ml" ...
#  $ RH.Corr              : chr  "2.00 %" "2.00 %" "2.00 %" "2.00 %" ...
#  $ Sonde.Total.O3       : chr  "242" "242" "242" "242" ...
#  $ Sonde.Total.O3..SBUV.: chr  "233 (36) DU" "233 (36) DU" "233 (36) DU" "233 (36) DU" ...
#  $ Level                : num  1010 10000 10000 10000 971 ...
#  $ Press                : num  0.005 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 ...
#  $ Alt                  : num  302 10000 10000 10000 302 ...
#  $ Pottp                : num  30.2 999.9 999.9 999.9 25.8 ...
#  $ Temp                 : num  24.6 999.9 999.9 999.9 20.7 ...
#  $ FtempV               : num  72 999 999 999 74 999 999 999 75 999 ...
#  $ Hum                  : num  1.65 99.9 99.9 99.9 1.68 99.9 99.9 99.9 1.48 99.9 ...
#  $ Ozone                : num  0.016 99.999 99.999 99.999 0.017 ...
#  $ Ozone.1              : num  0e+00 1e+02 1e+02 1e+02 5e-04 ...
#  $ Ozone.2              : num  38.1 999.9 999.9 999.9 38.1 ...
#  $ Ptemp                : num  3.93 1000 1000 1000 4.07 ...
#  $ O3                   : num  242 9999 9999 9999 241 ...

【讨论】:

  • 谢谢@r2evans。可能是我在 stackoverflow 中看到的最漂亮的解决方案之一。
  • @r2evans。别客气。只是尝试调整。我想知道将其重塑为只有 27 个变量的数据框。所有其他文件将按行而不是按列列出。我试过rbind,但没用。有什么想法吗?
  • do.call("rbind", alldfs) 应该可以工作,与dplyr::bind_rows(alldfs) 相同。两者都假定所有文件都具有相同的列名。
  • 当我浏览提取的数据框时,我发现它一遍又一遍地重复同一个文件。所以所有 29 个文件都有重复的值。我该如何解决这个问题?
  • 我没有看到。您是说Launch.Date(例如)是所有导入文件中的单个值吗?
猜你喜欢
  • 1970-01-01
  • 2021-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-05
  • 2019-04-27
相关资源
最近更新 更多