Je voudrais ajouter des lignes pour chaque point d'échantillonnage contenant les étapes de temps à autre avec des intervalles annuels. Donc, dans les lignes ajoutées, je souhaite modifier uniquement le contenu des colonnes «de» et «à» et conserver toutes les autres informations de la ligne ci-dessus.

Ce que j'ai en ce moment:

 > 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

Ce dont j'ai besoin:

 > 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  

Voici l'exemple de trame de données:

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)

Je suis nouveau sur R et c'est ma première question ici, alors pardonnez-moi si la question n'est pas formulée parfaitement, quelque chose manque ou si j'ai manqué une question similaire avec une solution à mon problème. Je suis reconnaissant pour tous les indices!

2
Siska 20 oct. 2020 à 12:33

2 réponses

Meilleure réponse

Voici une option tidyverse:

Nous créons une séquence annuelle de la colonne from à la colonne to et créons la colonne to qui est la valeur suivante de la valeur from pour chaque 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
Ronak Shah 20 oct. 2020 à 09:46

Vous pouvez créer des seq uences annuelles par ligne, rep manger chaque valeur deux fois pour créer un matrix dans lequel vous supprimez les lignes inutiles par la suite.

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
}))

Donne

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" ...

Données:

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))
1
jay.sf 20 oct. 2020 à 11:19