R 转换值列表中的日期和时间

R 转换值列表中的日期和时间,r,type-conversion,R,Type Conversion,我已经阅读了和其他相关的解决方案,但找不到这个解决方案的答案: 我有一个包含7个元素的字符串列表,其中前两个是日期和时间: > head(IOlow) [1] "20160928 142949 0.000172 0.000225 0.000015 0.000172 0.000765" [2] "20160928 164105 0.000163 0.000227 0.000017 0.000163 0.000908" [3] "20160928 172826 0.000176 0.00023

我已经阅读了和其他相关的解决方案,但找不到这个解决方案的答案: 我有一个包含7个元素的字符串列表,其中前两个是日期和时间:

> head(IOlow)
[1] "20160928 142949 0.000172 0.000225 0.000015 0.000172 0.000765"
[2] "20160928 164105 0.000163 0.000227 0.000017 0.000163 0.000908"
[3] "20160928 172826 0.000176 0.000238 0.000017 0.000173 0.001604"
现在我想用一个包含6个元素的列表替换每个这样的字符串,其中第一个元素是由前两个数字构建的DateTime对象,其他元素是浮点数字(而不是字符串)。所以我定义了这个辅助函数:

dateFormat <- "%Y%m%d %H%M%S"
function (x) {
    x <- strsplit(x, split=" ")
    w <- paste(x[[1]][1], x[[1]][2])
    str(w)
    x <- list(as.POSIXlt(w, format=dateFormat), as.double(x[[1]][3:7]))
}
结果如下所示:

> lapply(head(IOlow), to_numeric)
 chr "20160928 142949"
 chr "20160928 164105"
 chr "20160928 172826"
[[1]]
[[1]][[1]]
[1] "2016-09-28 14:29:49 CEST"

[[1]][[2]]
[1] 0.000172 0.000225 0.000015 0.000172 0.000765


[[2]]
[[2]][[1]]
[1] "2016-09-28 16:41:05 CEST"

[[2]][[2]]
[1] 0.000163 0.000227 0.000017 0.000163 0.000908


[[3]]
[[3]][[1]]
[1] "2016-09-28 17:28:26 CEST"

[[3]][[2]]
[1] 0.000176 0.000238 0.000017 0.000173 0.001604
出于我不理解的原因,R似乎在列表中创建了额外的列表(我认为我无法返回向量,因为列表中有不同的数据类型)。 也许只是有些函数没有以我需要的方式记录下来,以了解真正发生了什么

下一步将从列表列表中构建data.frame

我做错了什么,我该如何正确地做

系统信息:

> sessionInfo()
R version 3.3.1 (2016-06-21)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

locale:
[1] LC_COLLATE=German_Germany.1252  LC_CTYPE=German_Germany.1252   
[3] LC_MONETARY=German_Germany.1252 LC_NUMERIC=C                   
[5] LC_TIME=German_Germany.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

loaded via a namespace (and not attached):
[1] tools_3.3.1

我想你想要这样的东西,不是吗

to_numeric <- function(x,dateFormat) {
  x <- unlist(strsplit(as.character(x), split=" "))
  w <- paste(x[1], x[2])
  x <- list(as.POSIXlt(w, format=dateFormat), as.double(x[3:7]))
}

l <- apply(head(IOlow), 1, function(x) to_numeric(x, '%Y%m%d'))

l[1]

[[1]]
[1] "2016-09-28 IST"

[[2]]
[1] 0.000172 0.000225 0.000015 0.000172 0.000765

到_numeric在@A.Val建议的行中,您必须将其作为列表处理吗?如果它直接在某个文件中,它会更直接地读取,比如
read.delim
或者
readr::read\u delim

缺少这些,将字符串转换为假文件(有两个原因:(1)你的再现性,(2)如果你不能将其作为文件处理,现在你仍然可以使用这个答案):

IOlow考虑到

dat <- read.delim(textConnection(paste(IOlow, collapse = "\n")),
                  sep = " ", header = FALSE)
然后,我根据日期和时间构建了一个新的“when”变量(我在data.frame中添加了名称):


dateFormat是否需要使用
POSIXlt
?它以列表的形式在内部存储内容(可以是好的,也可以是坏的)。出于各种原因,我倾向于更多地使用
POSIXct
。为了消除一些混淆,您能提供所需的输出吗?据我所知,最终您希望看到一个包含6列的数据框,如1列表示日期,5列表示数据?通过设计直接将输入转换为数据帧的函数来跳过所有这些“列表混乱”怎么样?实际上直到你的帖子,我都不知道
POSIXct
POSIXlt
之间的区别是什么(谢谢!)。也许文档可以改进。关于输出格式:第一个列表元素应该可以由plot使用,并在以后的处理中以人类可读的格式显示为日期和/或时间(其余的元素作为可处理的数字)。够清楚吗?我愿意接受任何优雅的解决方案(因为我还在学习R)!相当酷:在这种情况下,我没有想到
read.delim()
。使用
dat[,-(1:2)]
删除前两列对我来说还是新鲜事(或者说在我的记忆中还没有解决)。坦白说,有几种方法可以剥这只猫的皮。也可以使用
readr::read_delim
(从文件中)、
tidyr::unite
lubridate::ymd_hms
、和
dplyr
将其粘合在一起(
dplyr
)。我确信它可以用
data.table
来完成,尽管我对它了解不够<代码>strsplit
如果您必须将其作为字符串向量使用,则可以使用它。顺便说一句:一个经常被遗忘的步骤或检查是为了确保时区正确。在这种情况下,“显式”将省去很多麻烦。解释为什么我不能从
readr::read_delim
开始(从给出的示例中不明显):这是我第一次尝试处理纯文本日志文件,而
IOlow
中的结果实际上是过滤和文本替换(regex)的结果日志文件中的行。不完全正确(我不确定我是否完全理解):我认为
strsplit()
返回元素列表;那么
unlist(strsplit(…)
的结果是什么呢?好的,由于一些模糊的原因,`strsplit()`返回一个列表,其中只有一个元素是结果元素的列表。
1
参数指向
apply()
的原因是什么?(过早点击回车键)似乎R喜欢将列表放入列表,只是因为它太酷了(或者混淆了…);-)@r2evans的解决方案在我看来更好,但这仍然是有用的。(1)由于向量中最好有6个值,而不是一个列表,所以只需要一个级别的索引:只是x[1],而不是x[[1]][1](2)对于数据帧IOlow的每一行,我们要应用函数,这就是为什么有参数1(3)最好向函数传递一个附加的dateFormat参数,使其更灵活。(4) 最后,dataframe的每一行现在将与输出列表中的一个元素(它本身是一个包含6个元素的列表)相对应。您说“太复杂”,但您是在接收原始数据,在R中执行正则表达式工作,然后尝试解析一个分隔文件?效率当然是不可能的(尤其是因为您必须手动将其转换为float),通过使用
read.delim
(或相关函数),您可以充分利用它们处理近乎原始的数据和数字的能力。但我认为这种方法——尽管它可能有效——更脆弱,而且可能更慢。尽管如此,我也有类似的需求,我发现最快(时间方面)和最安全的方法是使用
读线
,根据需要对数据进行按摩(例如正则表达式按摩),
写线
,返回到另一个文件,然后
readr::read\u csv
。做这件事的时间差别很大,不能轻易放弃。(坦率地说,我本应该使用python进行预读按摩,但我怀疑我和你一样,R是最接近的,并且被用于其他任何事情,所以…)。也许@r2evans展示了用于“按摩”的代码草图(作为相关问题的一般解决方案)?我并不是想诋毁这个提议,但我觉得它不适合我的情况。没有一个通用的解决方案:它只针对数据和需要修复的问题,以便使用标准的
read.*
函数
IOlow <- c("20160928 142949 0.000172 0.000225 0.000015 0.000172 0.000765",
           "20160928 164105 0.000163 0.000227 0.000017 0.000163 0.000908",
           "20160928 172826 0.000176 0.000238 0.000017 0.000173 0.001604")
dat <- read.delim(textConnection(paste(IOlow, collapse = "\n")),
                  sep = " ", header = FALSE)
dat
#         V1     V2       V3       V4      V5       V6       V7
# 1 20160928 142949 0.000172 0.000225 1.5e-05 0.000172 0.000765
# 2 20160928 164105 0.000163 0.000227 1.7e-05 0.000163 0.000908
# 3 20160928 172826 0.000176 0.000238 1.7e-05 0.000173 0.001604

dat$dt <- as.POSIXct(paste(dat$V1, dat$V2, sep = " "), format = "%Y%m%d %H%M%S")
dat <- dat[, -(1:2)]
dat
#         V3       V4      V5       V6       V7                  dt
# 1 0.000172 0.000225 1.5e-05 0.000172 0.000765 2016-09-28 14:29:49
# 2 0.000163 0.000227 1.7e-05 0.000163 0.000908 2016-09-28 16:41:05
# 3 0.000176 0.000238 1.7e-05 0.000173 0.001604 2016-09-28 17:28:26
dat <- read.delim(textConnection(paste(IOlow, collapse = "\n")),
                  sep = " ", header = FALSE)
split_line <- function (x) {
    x <- unlist(strsplit(x, split=" "))
}

IOlow <- lapply(IOlow, split_line)
IOlow <- data.frame(do.call(rbind, IOlow), stringsAsFactors=FALSE)
dateFormat <- "%Y%m%d %H%M%S"
IOlow$when <- with(IOlow,
                   as.POSIXct(paste(date, time, sep = " "), format=dateFormat))
for (n in names(IOlow)) {
    # convert all strings to double
    if ("character" %in% class(IOlow[,n])) {
        IOlow[n] <- lapply(IOlow[n], as.double)
    }
}