#r #dataframe #date
#r #фрейм данных #Дата
Вопрос:
Я хотел бы добавить строки для каждой точки выборки, содержащие временные интервалы с годовыми интервалами. Итак, в добавленных строках я хочу изменить только содержимое столбцов «от» и «до» и сохранить всю остальную информацию из строки выше.
Что у меня есть прямо сейчас:
> sample_points
point from to label
1 2004-05-01 2007-05-01 cropland
2 2009-05-01 2012-05-01 grassland
3 2014-05-01 2016-05-01 forest
Что мне нужно:
> sample_points
point from to label
1 2004-05-01 2005-05-01 cropland
1 2005-05-01 2006-05-01 cropland
1 2006-05-01 2007-05-01 cropland
2 2009-05-01 2010-05-01 grassland
2 2010-05-01 2011-05-01 grassland
2 2011-05-01 2012-05-01 grassland
3 2014-05-01 2015-05-01 forest
3 2015-05-01 2016-05-01 forest
Вот пример фрейма данных:
point <- c("1", "2", "3")
from <- as.Date(c("2004-05-01", "2009-05-01", "2014-05-01"))
to <- as.Date(c("2007-05-01", "2012-05-01", "2016-05-01"))
label <- c("cropland", "grassland", "forest")
sample_points <- data.frame(point, from, to, label)
Я новичок в R, и это мой первый вопрос здесь, поэтому, пожалуйста, простите меня, если вопрос сформулирован не идеально, чего-то не хватает или я пропустил аналогичный вопрос с решением моей проблемы.
Я благодарен за любые подсказки!
Ответ №1:
Вот один tidyverse
из вариантов :
Мы создаем годовую последовательность от from
столбца к to
столбцу и создаем to
столбец, который является следующим значением from
значения для каждого point
.
library(tidyverse)
sample_points %>%
mutate(from = map2(from, to, seq, by = 'year')) %>%
unnest(from) %>%
group_by(point) %>%
mutate(to = lead(from)) %>%
filter(!is.na(to))
# point from to label
# <chr> <date> <date> <chr>
#1 1 2004-05-01 2005-05-01 cropland
#2 1 2005-05-01 2006-05-01 cropland
#3 1 2006-05-01 2007-05-01 cropland
#4 2 2009-05-01 2010-05-01 grassland
#5 2 2010-05-01 2011-05-01 grassland
#6 2 2011-05-01 2012-05-01 grassland
#7 3 2014-05-01 2015-05-01 forest
#8 3 2015-05-01 2016-05-01 forest
Ответ №2:
Вы можете создавать годовые seq
значения по строкам, rep
дважды использовать каждое значение, чтобы создать a matrix
, где впоследствии вы удаляете ненужные строки.
res <- do.call(rbind, lapply(1:nrow(sample_points), function(m) {
cc <- c("from", "to")
dc <- as.character(do.call(seq, as.list(c(sample_points[m, cc], by="year"))))
if (length(dc) == 2) {
o <- sample_points[m, ]
} else {
dm <- suppressWarnings(matrix(rep(dc, each=2)[-1],,2,b=T))
dm <- if (nrow(dm) == 1) dm else dm[-nrow(dm), ]
o <- setNames(data.frame(sample_points[m, "point"], dm,
sample_points[m, "label"]),names(sample_points))
o[cc] <- lapply(o[cc], as.Date)
}
o
}))
Дает
res
# point from to label
# 1 1 2004-05-01 2005-05-01 cropland
# 2 1 2005-05-01 2006-05-01 cropland
# 3 1 2006-05-01 2007-05-01 cropland
# 4 2 2009-05-01 2010-05-01 grassland
# 5 2 2010-05-01 2011-05-01 grassland
# 6 2 2011-05-01 2012-05-01 grassland
# 7 3 2014-05-01 2015-05-01 forest
# 8 3 2015-05-01 2016-05-01 forest
Где
str(res)
# 'data.frame': 8 obs. of 4 variables:
# $ point: chr "1" "1" "1" "2" ...
# $ from : Date, format: "2004-05-01" ...
# $ to : Date, format: "2005-05-01" ...
# $ label: chr "cropland" "cropland" "cropland" "grassland" ...
Данные:
sample_points <- structure(list(point = c("1", "2", "3"), from = structure(c(12539,
14365, 16191), class = "Date"), to = structure(c(13634, 15461,
16922), class = "Date"), label = c("cropland", "grassland", "forest"
)), class = "data.frame", row.names = c(NA, -3L))