У меня есть большой набор данных, состоящий из нескольких нерегулярных временных рядов с определенным столбцом даты для каждого ряда. Я хочу преобразовать этот набор данных в фрейм данных с уникальным столбцом даты или в объект зоопарка.
Я пробовал read_xls(), read.zoo(). Я попытался изменить форму с помощью pivot_longer(). Я искал в Интернете, но пока не нашел решения.
date1 Var1 date2 Var2 date3 Var3
2023-01-13 100.1 2023-01-11 99.7 2022-11-24 102.3
2023-01-16 104.5 2023-01-12 NA 2022-11-25 99.9
2023-01-17 101.6 2023-01-13 99.9 2022-11-28 99.3
2023-01-18 101.8 2023-01-16 99.1 2022-11-29 NA
2023-01-19 NA 2023-01-17 99.5 2022-11-30 NA
Каким должно быть окончательное значение даты «2023-01-13», поскольку она имеет 2 значения: 100,1 и 99,9?
На дату «2023-01-13» Var1 имеет значение 100,1, Var2 — 99,9, а Var3 — нет данных.
Я дам этот ответ, пока кто-нибудь не придумает что-то более элегантное.
library(tidyverse)
dat <- structure(list(date1 = structure(c(19370, 19373, 19374, 19375,
19376), class = "Date"), Var1 = c(100.1, 104.5, 101.6, 101.8,
NA), date2 = structure(c(19368, 19369, 19370, 19373, 19374
), class = "Date"), Var2 = c(99.7, 99.8, 99.9, NA, NA), date3 = structure(c(19320,
19321, 19324, 19325, 19326), class = "Date"), Var3 = c(102.3,
99.9, 99.3, 100.5, 100.1)), row.names = c(NA, -5L), class = c("tbl_df",
"tbl", "data.frame"))
dat2 <- dat %>%
pivot_longer(cols = contains("date"),
names_to = "date") %>%
select(date, value, contains("Var")) %>%
arrange(date) %>%
mutate(id = group_indices(group_by(., date))) %>%
select(contains("Var"), date = value, id)
var_nms <- names(select(dat2, contains("Var")))
for (i in seq_along(var_nms)){
dat2[[var_nms[i]]] <- if_else(dat2$id == i, dat2[[var_nms[i]]],
NA_real_)
}
out <- dat2 %>%
mutate(Var = do.call(coalesce, pick(contains("Var")))) %>%
select(date, Var)
out
#> # A tibble: 15 x 2
#> date Var
#> <date> <dbl>
#> 1 2023-01-13 100.
#> 2 2023-01-16 104.
#> 3 2023-01-17 102.
#> 4 2023-01-18 102.
#> 5 2023-01-19 NA
#> 6 2023-01-11 99.7
#> 7 2023-01-12 99.8
#> 8 2023-01-13 99.9
#> 9 2023-01-16 NA
#> 10 2023-01-17 NA
#> 11 2022-11-24 102.
#> 12 2022-11-25 99.9
#> 13 2022-11-28 99.3
#> 14 2022-11-29 100.
#> 15 2022-11-30 100.
Created on 2023-04-12 with reprex v2.0.2
Используя данные, показанные воспроизводимо в примечании в конце, предположим, что требуется объект зоопарка с отдельным столбцом для каждого столбца, не связанного с датой.
Сначала создайте вектор группировки g
, который выглядит как c("Var1", "Var1", "Var2", "Var2", "Var3", "Var3")
, а затем преобразуйте DF
в список и разделите его на g
, дающий s
. Наконец, преобразуйте каждый компонент s
в объект зоопарка и объедините их с помощью cbind
. (Если требуется фрейм данных, используйте fortify.zoo
в результате.)
library(zoo)
g <- rep(names(DF)[sapply(DF, is.numeric)], each = 2)
s <- split(as.list(DF), g)
do.call("cbind", lapply(s, function(x) read.zoo(as.data.frame(x))))
давая:
Var1 Var2 Var3
2022-11-24 NA NA 102.3
2022-11-25 NA NA 99.9
2022-11-28 NA NA 99.3
2022-11-29 NA NA NA
2022-11-30 NA NA NA
2023-01-11 NA 99.7 NA
2023-01-12 NA NA NA
2023-01-13 100.1 99.9 NA
2023-01-16 104.5 99.1 NA
2023-01-17 101.6 99.5 NA
2023-01-18 101.8 NA NA
2023-01-19 NA NA NA
Это может быть представлено в виде конвейера следующим образом:
g <- rep(names(DF)[sapply(DF, is.numeric)], each = 2)
DF |>
as.list() |>
split(g) |>
lapply(function(x) read.zoo(as.data.frame(x))) |>
do.call(what = "cbind")
или
DF |>
as.list() |>
(\(x) split(x, rep(names(x)[sapply(x, is.numeric)], each = 2)))() |>
lapply(\(x) read.zoo(as.data.frame(x))) |>
do.call(what = "cbind")
Lines <- "date1 Var1 date2 Var2 date3 Var3
2023-01-13 100.1 2023-01-11 99.7 2022-11-24 102.3
2023-01-16 104.5 2023-01-12 NA 2022-11-25 99.9
2023-01-17 101.6 2023-01-13 99.9 2022-11-28 99.3
2023-01-18 101.8 2023-01-16 99.1 2022-11-29 NA
2023-01-19 NA 2023-01-17 99.5 2022-11-30 NA"
DF <- read.table(text = Lines, header = TRUE)
на самом деле работает с этим примером, но при работе с моим набором данных я получаю следующее сообщение об ошибке: «Ошибка в read.zoo(as.data.frame(x)) : индекс имеет 206 неверных записей в строках данных: 348 349 ... "
Дубликата нет. Ошибка возникает из-за NA в конце моего набора данных. read.zoo не может читать из строк, заполненных NA. Я читал темы о разнице между пустыми ячейками и NA. Я пытался изменить их значение, используя различные стратегии, такие как na.fill() и другие параметры, такие как na = "". Но это не работает.
Проблема только в датах АН. NA в значениях не проблема. Замените as.data.frame(x)
на na.omit(as.data.frame(x))
Скажите, как должен выглядеть конечный результат?