Convertir las coordenadas de intervalos divididos a coordenadas de intervalos continuos.
Tengo un data.frame
en el cual cada id
se mapea a varios intervalos lineales no contiguos, que no se superponen y están ordenados en orden ascendente:
df <- data.frame(id = c(rep("id1",3),rep("id2",4)),
start = c(101,220,307,550,658,742,855),
end = c(154,246,326,625,712,811,944),
stringsAsFactors = F)
Me gustaría agregar nuevas columnas de start
y end
que sumen acumulativamente las longitudes de los intervalos y muestren las coordenadas de inicio y fin acumulativas.
Entonces, para el ejemplo df
anterior, estas nuevas columnas de start
y end
(cum.start
, cum.end
) serán:
df$cum.start <- c(1,55,82,1,77,132,202)
df$cum.end <- c(54,81,101,76,131,201,291)
¿Hay alguna forma de hacer esto usando dplyr
?
davy.ai
Sí, hay una solución
dplyr
para este problema. Podemos usar la funcióngroup_by
para agrupar eldata.frame
porid
, y luego usar la funciónmutate
para añadir las nuevas columnascum.start
ycum.end
. Luego podemos usar la funcióncumsum
para calcular la suma acumulada dentro de cada grupo.Aquí está el código:
“`{r}
library(dplyr)
df %>%
group_by(id) %>%
mutate(cum.start = c(start[1], diff(end) + 1),
cum.end = cumsum(diff(cum.start))) %>%
ungroup()
Una tabla: 7 x 5
id start end cum.start cum.end
1 id1 101 154 1 54
2 id1 220 246 55 81
3 id1 307 326 82 101
4 id2 550 625 1 76
5 id2 658 712 77 131
6 id2 742 811 132 201
7 id2 855 944 202 291
“`
En la función
mutate
, primero calculamos la diferencia entreend
y su correspondientestart
anterior, y le sumamos 1 para obtener la longitud de cada intervalo. Luego usamoscumsum
para calcular la suma acumulada de estas longitudes de intervalo, lo que nos da las coordenadas de inicio y fin acumulativas para cada grupo. Por último, usamosungroup
para eliminar la agrupación.