J'ai un ensemble de données contenant une mesure et le jour précis où elle a été collectée. Je voudrais reproduire les valeurs entre les jours, jusqu'au dernier jour de mesure. Par exemple, voici les données avant leur réplication:
Measurement Day Subject1 .86 1 Subject1 .86 2 Subject1 .86 3 Subject1 .86 4 Subject1 .86 5 Subject1 .86 6 Subject1 .91 7 Subject1 .91 8 Subject1 .83 9 Subject2 .77 0 Subject2 .77 1 Subject2 .77 2 Subject2 .77 3 Subject2 .77 4 Subject2 .82 5 Subject2 .82 6 Subject2 .82 7 Subject2 .82 8 Subject2 .82 9 Subject2 .82 10 Subject2 .82 11 Subject2 .86 12
Je voudrais modifier l'ensemble de données ci-dessus dans R pour qu'il ressemble à ce qui suit:
Measurement Day Subject1 .86 1 Subject1 .91 7 Subject1 .83 9 Subject2 .77 0 Subject2 .82 5 Subject2 .86 12
3 Réponses :
Nous pouvons utiliser complete
. En supposant que les données d'entrée de l'OP sont de la matrice
(car data.frame
n'autorise pas les noms de lignes en double et en supposant qu'il y a row.names - wow beaucoup d'hypothèses), créez un data.frame avec as.data.frame
tandis que cbind
insère le row.names sous forme de colonne, groupé par 'Subject', utilisez complete
pour obtenir la séquence complète de "Jour", puis remplir
les NA dans "Mesure" avec la valeur précédente non-NA
dat <- structure(c(0.86, 0.91, 0.83, 0.77, 0.82, 0.86, 1, 7, 9, 0, 5, 12), .Dim = c(6L, 2L), .Dimnames = list(c("Subject1", "Subject1", "Subject1", "Subject2", "Subject2", "Subject2"), c("Measurement", "Day")))
library(tidyverse) cbind(Subject = row.names(dat), as.data.frame(dat)) %>% group_by(Subject) %>% complete(Day = first(Day):last(Day)) %>% fill(Measurement) %>% select(Subject, Measurement, Day) # A tibble: 22 x 3 # Groups: Subject [2] # Subject Measurement Day # <fct> <dbl> <dbl> # 1 Subject1 0.86 1 # 2 Subject1 0.86 2 # 3 Subject1 0.86 3 # 4 Subject1 0.86 4 # 5 Subject1 0.86 5 # 6 Subject1 0.86 6 # 7 Subject1 0.91 7 # 8 Subject1 0.91 8 # 9 Subject1 0.83 9 310 Subject2 0.77 0 # ⦠with 12 more rows
> foo = function(x){ + r = range(x) + as.numeric(seq(r[1], r[2]) %in% x) + } > do.call(rbind, lapply(split(1:NROW(dat), row.names(dat)), function(i){ + temp = dat[i,] + temp = temp[with(rle(cumsum(foo(temp[,"Day"]))), rep(seq_along(lengths), lengths)),] + temp[,"Day"] = ave(temp[, "Day"], temp[,"Day"], FUN = function(x) x + (1:length(x) - 1)) + temp + })) Measurement Day Subject1 0.86 1 Subject1 0.86 2 Subject1 0.86 3 Subject1 0.86 4 Subject1 0.86 5 Subject1 0.86 6 Subject1 0.91 7 Subject1 0.91 8 Subject1 0.83 9 Subject2 0.77 0 Subject2 0.77 1 Subject2 0.77 2 Subject2 0.77 3 Subject2 0.77 4 Subject2 0.82 5 Subject2 0.82 6 Subject2 0.82 7 Subject2 0.82 8 Subject2 0.82 9 Subject2 0.82 10 Subject2 0.82 11 Subject2 0.86 12
Légèrement basé sur la réponse de @akrun
library(tidyverse) df <- cbind(Subject = row.names(dat), as.data.frame(dat)) df %>% group_by(Subject) %>% mutate(day_diff = c(diff(Day), 1)) %>% uncount(day_diff) %>% mutate(Day = first(Day):last(Day)) %>% ungroup()