在reshape2的dcast函数中,POSIXct值变为数值类型。

7

我正在尝试使用最新的包(1.2.1)中的dcast函数,将值变量为POSIXct类型的数据框(或data.table)去规范化,但在生成的数据框中,日期值失去了它们的POSIXct类并变成了数字。

如果我想要这些值作为POSIXct类型返回,我是否真的需要对每个生成的列使用as.POSIXct(),或者我漏掉了什么?

x <- c("a","b");
y <- c("c","d");
z <- as.POSIXct(c("2012-01-01 01:01:01","2012-02-02 02:02:02"));
d <- data.frame(x, y, z, stringsAsFactors=FALSE);
str(d);
library(reshape2);
e <- dcast(d, formula = x ~ y, value.var = "z");
str(e);

上述语句的运行结果(注意新列c和d是数字时期秒,而不是POSIXct):
> x <- c("a","b");
> y <- c("c","d");
> z <- as.POSIXct(c("2012-01-01 01:01:01","2012-02-02 02:02:02"));
> d <- data.frame(x, y, z, stringsAsFactors=FALSE);
> str(d);
'data.frame':   2 obs. of  3 variables:
 $ x: chr  "a" "b"
 $ y: chr  "c" "d"
 $ z: POSIXct, format: "2012-01-01 01:01:01" "2012-02-02 02:02:02"
> library(reshape2);
> e <- dcast(d, formula = x ~ y, value.var = "z");
> str(e);
'data.frame':   2 obs. of  3 variables:
 $ x: chr  "a" "b"
 $ c: num  1.33e+09 NA
 $ d: num  NA 1.33e+09

我感到困惑。如果添加新行以便在结果数据框中没有NA值,行为仍然存在,但是相同的 acast 调用会给出预期的 POSIXct 结果。 - Justin
3个回答

10

执行debug(dcast)debug(as.data.frame.matrix),然后逐步跟踪由dcast()调用启动的计算,将揭示as.data.frame.matrix()中的这些行存在问题:

if (mode(x) == "character" && stringsAsFactors) {
    for (i in ic) value[[i]] <- as.factor(x[, i])
}
else {
    for (i in ic) value[[i]] <- as.vector(x[, i])
}

到目前为止,POSIXct对象的模式为"numeric",因此评估将遵循第二个分支,将结果转换为数字。

如果您使用dcast(),则似乎需要对结果进行后处理,如果您有正确的origin,这应该不会太难。类似这样(没有完全正确地得到origin),就可以解决问题:

e[-1] <- lapply(e[-1], as.POSIXct, origin="1960-01-01")

顺便提一下,基础R的reshape()函数会保留POSIXct值,但需要你编辑生成列的名称...

reshape(d, idvar="x", timevar="y",  direction="wide")
#   x                 z.c                 z.d
# 1 a 2012-01-01 01:01:01                <NA>
# 2 b                <NA> 2012-02-02 02:02:02

@josh-obrien:感谢您的快速响应和调试信息。罪魁祸首是as.vector,它只返回原子类型。最终我将使用data.table,因为我要处理数千列和数万行数据,所以我会看看lapply语法是否适用。 - gkaupas
根据Hadley的要求,在此处报告[https://github.com/hadley/reshape/issues/26]。 - gkaupas

1

当转换/扩展数据集时,为确保日期完整性,预处理和/或后处理可能非常麻烦。

在这方面,除非您需要的重塑很复杂,否则来自 tidyr 包的 pivot_wider() 尊重日期对象 - 在此过程中不进行转换。此外,它还可以更好地控制转换/扩展过程,从而避免后处理步骤 (https://tidyr.tidyverse.org/reference/pivot_wider.html)。


不鼓励基于链接的答案,因为链接可能会失效。您能否考虑用一些直接回答问题的代码来充实您的答案? - Peter

0

我也遇到了这个问题。我的解决方法是先将日期字段转换为字符型,然后进行dcast操作,最后再转换回日期格式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接