Значения POSIXct становятся числовыми в reshape2 dcast

Я пытаюсь использовать dcast из последнего пакета reshape2 (1.2.1) для денормализации фрейма данных (или data.table), где value.var - это тип POSIXct, но в результирующем фрейме данных значения даты потерялись их класс POSIXct и стать числовым.

Действительно ли мне нужно as.POSIXct() для каждого сгенерированного столбца, если я хочу вернуть значения как 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

2 ответа

Решение

Дела 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")

FWIW, база R's 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

Предварительная и / или постобработка целостности дат при приведении / расширении набора данных может быть очень обременительной.

В этом отношении, если изменение, которое вам нужно, не является сложным, pivot_wider() из пакета tidyr уважительно относится к объектам дат - без преобразования на этом пути. Кроме того, он дает гораздо больший контроль над процессом преобразования / расширения, тем самым избегая шагов постобработки (https://tidyr.tidyverse.org/reference/pivot_wider.html).

Я только что столкнулся с этой проблемой. Я решил это, сначала приведя поле даты в символ, затем dcast, а затем преобразовав обратно в дату.

Другие вопросы по тегам