#r #tidyverse
#r #tidyverse
Вопрос:
У меня есть несколько пар даты / значения в больших файлах csv, которые я хотел бы очистить автоматически. Количество пар неизвестно. Ниже приведен пример и способ ручной очистки этих данных. Как я могу это автоматизировать? Пожалуйста, дайте мне знать, если потребуется дополнительная информация.
# I have a data frame with multiple date/value pairs
# the number of pairs is varying
# in a simple example 2 date/value pairs like this
library(magrittr)
suppressMessages(library(dplyr))
date1 <- Sys.Date() seq(1, 10)
type1 <- as.integer(runif(10) * 1000)
date2 <- c(Sys.Date() seq(1, 8, 2), rep(NA, 6))
type2 <- c(as.integer(runif(4) * 1000), rep(NA, 6))
df_raw <- data.frame(date1, type1, date2, type2)
df_raw
#> date1 type1 date2 type2
#> 1 2021-01-23 908 2021-01-23 344
#> 2 2021-01-24 853 2021-01-25 849
#> 3 2021-01-25 627 2021-01-27 952
#> 4 2021-01-26 491 2021-01-29 597
#> 5 2021-01-27 237 <NA> NA
#> 6 2021-01-28 50 <NA> NA
#> 7 2021-01-29 101 <NA> NA
#> 8 2021-01-30 135 <NA> NA
#> 9 2021-01-31 759 <NA> NA
#> 10 2021-02-01 943 <NA> NA
# I could manually clean up
# to get the expected result
df1 <- df_raw[, 1:2] %>%
mutate(type = "type1") %>%
filter(!is.na(date1)) %>%
rename(date = date1, value = type1)
df2 <- df_raw[, 3:4] %>%
mutate(type = "type2") %>%
filter(!is.na(date2)) %>%
rename(date = date2, value = type2)
rbind(df1, df2)
#> date value type
#> 1 2021-01-23 908 type1
#> 2 2021-01-24 853 type1
#> 3 2021-01-25 627 type1
#> 4 2021-01-26 491 type1
#> 5 2021-01-27 237 type1
#> 6 2021-01-28 50 type1
#> 7 2021-01-29 101 type1
#> 8 2021-01-30 135 type1
#> 9 2021-01-31 759 type1
#> 10 2021-02-01 943 type1
#> 11 2021-01-23 344 type2
#> 12 2021-01-25 849 type2
#> 13 2021-01-27 952 type2
#> 14 2021-01-29 597 type2
Создано 2021-01-22 пакетом reprex (версия 0.3.0)
Редактировать
Немного более сложный пример
structure(list(date1 = structure(c(18650, 18651, 18652, 18653,
18654, 18655, 18656, 18657, 18658, 18659), class = "Date"), type1 = c(922L,
795L, 646L, 363L, 692L, 843L, 799L, 168L, 758L, 888L), date2 = structure(c(18650,
18652, 18654, 18656, NA, NA, NA, NA, NA, NA), class = "Date"),
type2 = c(158L, 146L, 550L, 830L, NA, NA, NA, NA, NA, NA),
date3 = structure(c(18650, 18652, 18654, 18656, NA, NA, NA,
NA, NA, NA), class = "Date"), type3 = c(659L, 930L, 688L,
749L, NA, NA, NA, NA, NA, NA), date4 = structure(c(18650,
18651, 18652, 18653, 18654, 18655, NA, NA, NA, NA), class = "Date"),
type4 = c(743L, 497L, 558L, 174L, 187L, 937L, NA, NA, NA,
NA), date5 = structure(c(18650, 18652, 18654, 18656, NA,
NA, NA, NA, NA, NA), class = "Date"), type5 = c(484L, 845L,
784L, 640L, NA, NA, NA, NA, NA, NA), date6 = structure(c(18650,
18652, 18654, 18656, NA, NA, NA, NA, NA, NA), class = "Date"),
type6 = c(688L, 587L, 113L, 747L, NA, NA, NA, NA, NA, NA),
daten = structure(c(18650, 18653, 18656, NA, NA, NA, NA,
NA, NA, NA), class = "Date"), typen = c(110L, 876L, 809L,
NA, NA, NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA,
-10L))
Ответ №1:
Я думаю, что ваше решение кажется мне подходящим. Другим вариантом было бы объединить обе части фрейма данных по дате, а затем развернуть дольше.
Для более чем одной пары я бы разделил фрейм данных на n блоков по 2 столбца, а затем переименовал все столбцы даты, а затем использовал purrr::reduce
library(tidyverse)
pairs <- split(seq_along(mydat), ceiling(seq_along(mydat)/2))
ls_dat <- lapply(pairs, function(x) mydat[x] )
ls_dat <- lapply(ls_dat, function(x) rename(x, date = starts_with("date")))
purrr::reduce(ls_dat, full_join, by = "date") %>%
pivot_longer(names_to = "type", values_to = "value", cols = starts_with("type")) %>%
drop_na("value")
#> # A tibble: 35 x 3
#> date type value
#> <date> <chr> <int>
#> 1 2021-01-23 type1 922
#> 2 2021-01-23 type2 158
#> 3 2021-01-23 type3 659
#> 4 2021-01-23 type4 743
#> 5 2021-01-23 type5 484
#> 6 2021-01-23 type6 688
#> 7 2021-01-23 typen 110
#> 8 2021-01-24 type1 795
#> 9 2021-01-24 type4 497
#> 10 2021-01-25 type1 646
#> # … with 25 more rows
данные
mydat <- structure(list(date1 = structure(c(18650, 18651, 18652, 18653, 18654, 18655, 18656, 18657, 18658, 18659), class = "Date"), type1 = c(922L, 795L, 646L, 363L, 692L, 843L, 799L, 168L, 758L, 888L), date2 = structure(c(18650, 18652, 18654, 18656, NA, NA, NA, NA, NA, NA), class = "Date"), type2 = c(158L, 146L, 550L, 830L, NA, NA, NA, NA, NA, NA), date3 = structure(c(18650, 18652, 18654, 18656, NA, NA, NA, NA, NA, NA), class = "Date"), type3 = c(659L, 930L, 688L, 749L, NA, NA, NA, NA, NA, NA), date4 = structure(c(18650, 18651, 18652, 18653, 18654, 18655, NA, NA, NA, NA), class = "Date"), type4 = c(743L, 497L, 558L, 174L, 187L, 937L, NA, NA, NA, NA), date5 = structure(c(18650, 18652, 18654, 18656, NA, NA, NA, NA, NA, NA), class = "Date"), type5 = c(484L, 845L, 784L, 640L, NA, NA, NA, NA, NA, NA), date6 = structure(c(18650, 18652, 18654, 18656, NA, NA, NA, NA, NA, NA), class = "Date"), type6 = c(688L, 587L, 113L, 747L, NA, NA, NA, NA, NA, NA), daten = structure(c(18650, 18653, 18656, NA, NA, NA, NA, NA, NA, NA), class = "Date"), typen = c(110L, 876L, 809L, NA, NA, NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, -10L))
Комментарии:
1. Как бы вы обработали 20 пар даты / значения?
2. @Birger ах, я вижу 🙂 — не могли бы вы привести пример с четырьмя или, может быть, даже лучше, с 6 столбцами? в идеале отправлять данные с помощью dput