2017-09-27 3 views
2

J'ai utilisé un logiciel de suivi vidéo pour suivre les animaux lorsqu'ils se déplaçaient dans une arène. Les données sont les coordonnées X, Y (en pixels) de la position de l'animal à l'instant Z (dans le numéro d'image). Un exemple dataframe ressemble:Définir la largeur d'un chemin et calculer la superficie

x <- c(1,2,3,4,4,4,4,3,2,1) 
y <- c(1,2,3,4,3,2,1,2,3,4) 
z <- 1:length(x) 
df <- data.frame(x, y, z) 

Je suis intéressé par le comportement de l'animal et souhaitez calculer une mesure de « zone d'arène exploré. » Je ne suis pas sûr de la meilleure façon d'y parvenir, mais ma première pensée est de créer un chemin pas à pas à partir des points, puis de définir une largeur de tampon sur le chemin pour créer un polygone, et enfin, calculer la superficie de l'avion sous le polygone. Visuellement, je pouvais imaginer quelque chose comme:

plot(x, y, type = "o", lwd = 20) 

enter image description here

Je ne suis pas connu dans les données spatiales comme celles-ci, mais je pense je pourrais pixelliser ce chemin? Malheureusement, la commande lwd n'est pas absolue, donc si mon avion se développe, la largeur de la ligne ne sera pas mise à l'échelle avec elle.

Je préférerais utiliser un logiciel plutôt qu'un logiciel SIG.

Je suppose qu'il existe une solution plus élégante?

Répondre

2

Je ne suis pas un expert dans l'étude de la voie des animaux, mais je pense que c'est une bonne idée.

Nous pouvons utiliser le package sf, qui est la norme de la prochaine génération de la classe et les méthodes d'analyse des données spatiales dans l'affaire R.

Pour illustrer comment cela fonctionne, nous allons commencer par un exemple simple. Nous allons tracer une ligne allant de c(0, 1) à c(1, 1). Nous allons ensuite créer un tampon avec une distance égale à 1. Enfin, nous calculerons la surface de la zone tampon.

library(sf) 

# Create a simple feature object based on df 
ps <- as.matrix(rbind(c(0, 1), c(1, 1))) 
ls <- st_linestring(ps) 
# View the line 
plot(ls) 

enter image description here

# Create a buffer zone 
ls_buffer <- st_buffer(ls, dist = 1) 

# View ls_buffer 
plot(ls_buffer) 

enter image description here

# Calculate the area 
st_area(ls_buffer) 
[1] 5.140157 

La ligne et la zone tampon semble bon. Nous pouvons également calculer la zone en utilisant la fonction st_area. La forme de la zone tampon est similaire à un rectangle avec une largeur égale à 1 et une hauteur égale à 2, plus un cercle de rayon égal à 1. Nous pouvons calculer la surface en utilisant le code suivant. Le résultat est similaire à ce que nous avons obtenu de la fonction st_area.

2 * 1 + 1 * 1 * pi 
[1] 5.141593 

Maintenant, il est facile de modifier les codes ci-dessus pour votre exemple. Je définis la distance du tampon à 0,1, mais vous devrez déterminer une distance tampon raisonnable.

# Create example data frame 
x <- c(1,2,3,4,4,4,4,3,2,1) 
y <- c(1,2,3,4,3,2,1,2,3,4) 
z <- 1:length(x) 
df <- data.frame(x, y, z) 

# Create a simple feature object based on df 
ps <- as.matrix(df[, c("x", "y")]) 
ls <- st_linestring(ps) 
# View the line 
plot(ls) 

enter image description here

# Create a buffer zone 
ls_buffer <- st_buffer(ls, dist = 0.1) 

# View ls_buffer 
plot(ls_buffer) 

enter image description here

# Calculate the area 
st_area(ls_buffer) 
[1] 2.263725 

Le paquet sf est assez nouveau, donc je suis encore à apprendre et il y a probablement beaucoup de fonctionnalités que je ne connais pas encore. S'il vous plaît visitez ce site Web de paquet sur CRAN (https://cran.r-project.org/web/packages/sf/index.html) et accéder à ces vignettes si vous voulez en savoir plus.

1

Cette approche implique des techniques SIG dans R mais je pense que c'est assez simple et suit les trois étapes que vous avez énoncées.

library(sp) 
library(rgeos) 
library(dplyr) 

#Convert points to path (SpatialLines object)  
SOlines <- Line(coordinates(df[,1:2])) %>% list() %>% Lines(ID="test") %>% list() %>% SpatialLines() 
#Buffer the path into a polygon 
area <- rgeos::gBuffer(SOlines,width = .1, byid = T) 
#Calculate the area within the Polygon 
rgeos::gArea(area,byid=T) 
     test 
    2.262897 

Le paquet sf (comme dans la réponse de JCT) a une façon plus simple de créer le chemin de la ligne. Je ne suis pas encore familier avec ce paquet mais je vais garder cette réponse pour l'instant comme une bonne chose à propos de l'utilisation de l'approche de SpatialLines est que vous pouvez stocker plusieurs lignes dans un objet et ensuite calculer toutes les zones dans un appel de gArea.