strptime - 在 csv 文件中设置数据格式

strptime - set format with data in csv file

示例原始数据:

1
Mon Apr 06 23:55:14 PDT 2009

2
Tue Apr 07 01:16:43 PDT 2009

3
Tue Apr 07 03:06:17 PDT 2009

我在使用 strptime 进行格式化时遇到问题,因为我有来自 csv 文件的数据。

dates <- read.csv(file = "Australia_timestamp.csv")
colnames(dates) <- c("Date")
format <- "%a %b %d %H:%M:%S %z %Y"
dates <-strptime(dates[], format = format)

输出:

NA

如何通过没有 NA 和正确格式的输出来解决这个问题?

您得到的 NA 是因为 %z 没有捕获 PDT。它属于 %Z,因为它不是数字,但 strptime 不支持 %Z 输入,因为字符缩写不是明确的。 PDT 是 UTC-7,因此要使用 strptime 捕获时间戳,您的字符串必须是

Tue Apr 07 03:06:17 -0700 2009

解决问题的方法取决于您拥有的数据。如果您所有的时间戳都在 PDT 中,您只需将所有字符串中的 PDT 替换为 -0700:

dates$Date <- gsub("PDT", "-0700", dates$Date)
dates$Date <- strptime(dates$Date, format = format)

1) 主题引用了一个 csv 文件,但显示的数据不是 csv 格式。我们将假设问题中显示的表格是正确的,并且输入文件仅包含第一行 1,第二行描述 date/time,第三行是空白等等,如末尾的注释所示.

我们逐行读取它,然后在连续的行前面加上num: datetime: 和一个空字符串。这会将它转换为 debian 控制格式形式 (dcf),因此我们可以使用 read.dcf 来读取它并给出一个字符矩阵。将其转换为数据框,使用 convert.type 将第一列转换为数字并将第二列转换为 POSIXct。

下面管道中的前两行是为了利用注释中的 Lines 来重现,但要从文件中读取相同内容,只需将管道中的前两行替换为类似这样的内容, "myfile" |> 其中 myfile 是输入文件的名称。

没有使用包。

prefix <- \(x) paste(rep(c("num:", "time:", ""), length = length(x)), x)

Lines |>
  textConnection(name = "") |>
  readLines() |>
  trimws() |>
  prefix() |> 
  textConnection(name = "") |>
  read.dcf() |>
  as.data.frame() |>
  type.convert(as.is = TRUE) |>
  transform(time = as.POSIXct(time, format = "%a %b %d %H:%M:%S PDT %Y"))

给这个 data.frame:

  num                time
1   1 2009-04-06 23:55:14
2   2 2009-04-07 01:16:43
3   3 2009-04-07 03:06:17

2) 另一种方法是将数据转换为矩阵,如图所示,然后按上述步骤进行操作。

Lines |>
  textConnection(name = "") |>
  read.table(sep = "?", strip.white = TRUE) |>
  unlist() |>
  matrix(ncol = 2, byrow = TRUE, dimnames = list(NULL, c("num", "time"))) |>
  as.data.frame() |>
  type.convert(as.is = TRUE) |>
  transform(time = as.POSIXct(time, format = "%a %b %d %H:%M:%S PDT %Y"))

3) 如果问题中显示的格式是错误的,这意味着 1, 2, 3, ... 出现在同一行的日期时间之前像这样然后逐行读取它,用逗号替换第一个 space 并将其读入具有指定列名的数据框中。最后将时间列转换为POSIXct。

Lines2 <- "1 Mon Apr 06 23:55:14 PDT 2009
2 Tue Apr 07 01:16:43 PDT 2009
3 Tue Apr 07 03:06:17 PDT 2009"

Lines2 |>
  textConnection(name = "") |>
  readLines() |>
  trimws() |>
  sub(pattern = " ", replacement = ",") |>
  textConnection(name = "") |>
  read.table(sep = ",", col.names = c("num", "time"), strip.white = TRUE) |>
  transform(time = as.POSIXct(time, format = "%a %b %d %H:%M:%S PDT %Y"))

4) 如果输入确实是一个 csv 文件但没有第 3 行中所示的列 headers 那么它就更容易了:

Lines3 <- "1,Mon Apr 06 23:55:14 PDT 2009
2,Tue Apr 07 01:16:43 PDT 2009
3,Tue Apr 07 03:06:17 PDT 2009"

Lines3 |>
  textConnection(name = "") |>
  read.table(sep = ",", col.names = c("num", "time"), strip.white = TRUE) |>
  transform(time = as.POSIXct(time, format = "%a %b %d %H:%M:%S PDT %Y"))

备注

Lines <- "1
Mon Apr 06 23:55:14 PDT 2009

2
Tue Apr 07 01:16:43 PDT 2009

3
Tue Apr 07 03:06:17 PDT 2009"

我们可以使用 parse_date 来自 parsedate

library(tibble)
library(parsedate)
lines1 <- lines[nzchar(lines)]
tibble(num = lines1[c(TRUE, FALSE)], time = parse_date(lines1[c(FALSE, TRUE)]))

-输出

# A tibble: 3 × 2
  num   time               
  <chr> <dttm>             
1 1     2009-04-06 23:55:14
2 2     2009-04-07 01:16:43
3 3     2009-04-07 03:06:17

数据

lines <- readLines(textConnection("1
Mon Apr 06 23:55:14 PDT 2009

2
Tue Apr 07 01:16:43 PDT 2009

3
Tue Apr 07 03:06:17 PDT 2009"))
# or read from the file
lines <- readLines("file.txt")