I have animal location data. I am attempting to create random locations within a 20 km buffer around each location for each animal. I have working code to generate random locations (+ one used location). I'm now attempting to wrap another for loop around this working loop so that I can store random + used locations in a dataframe for each of 401 animals. I can't figure out how to index the 2nd dataframe which needs to hold all random + used locations for every animal.
A subset of my data looks something like this where the dataframe is also an sf object:
df <- data.frame(matrix(ncol = 17, nrow = 200))
colnames(df) <- c('id', 'tod_', 'x', 'y', 'time', 'distance', 'speed',
'tdif', 'heading', 'BirdsID', 'sex', 'month', 'date', 'hunting',
'dist.km', 'hunting2', 'diel')
dat_sf_utm <- st_as_sf(dat, coords = c("x", "y"), crs = 5070)
Then I begin the for loop. Heavily annotated.
# Create an empty data.frame to hold "random" and "used" points FOR EACH BIRD
temp2 <- data.frame(matrix(NA, nrow = 20 * ((nrow(dat_sf_utm)) - (length(unique(dat_sf_utm$BirdsID)))),
ncol = 20))
colnames(temp2) <- c("used", "x", "y", "distance", "BirdsID", "tod_", "time",
"tdif", "heading", "sex", "month", "date", "hunting", "dist.km",
"hunting2", "diel", "geometry", "id", "speed", "strata")
unique(dat_sf_utm$BirdsID)
for(j in unique(dat_sf_utm$BirdsID)){
trial <- dat_sf_utm %>%
group_by(BirdsID) %>% # Group by BirdsID
filter(BirdsID == j) %>% # filter BirdsID j
bind_cols(do.call(rbind, # Bind cols
(.$geometry)) %>% # Of "geometry"
as_tibble() %>% # And make them a tibble
setNames(c("x", "y")) # And call them xy
)
temp <- data.frame(matrix(NA, nrow = 20 * (nrow(trial)-1), # Make empty df to hold
ncol = 20)) # "random" and "used" locs
colnames(temp) <- c("used", "x", "y", "distance", "BirdsID", "tod_", "time",
"tdif", "heading", "sex", "month", "date", "hunting", "dist.km",
"hunting2", "diel", "geometry", "id", "speed", "strata")
for(i in 2:nrow(trial)){
x <- trial[i,] %>% # Take first row i of BirdsID j
ungroup() %>% # Ungroup the df
st_buffer(., 20000) %>% # Buffer that point by 20 km
st_intersection(., st_as_sf(water_poly)) %>% # Intersect the buffer by water polygon
st_sample(., 19, type = "random", exact = TRUE) %>% # Create 19 random points w/in buffer
st_cast(., "POINT") %>% # Make multipoint into point
as(., "Spatial") %>% # Then make it spatialpoints
as.data.frame(.) %>% # Then make it dataframe
mutate(used = 0, # Create column used and give randoms = 0
x = coords.x1, # Get rid of ugly column coords
y = coords.x2, # Calculate euclidean distance below
distance = sqrt((coords.x1 - trial$x[i-1])^2 + (coords.x2 - trial$y[i-1])^2)) %>%
dplyr::select(-coords.x1, -coords.x2) %>% # Officially get rid of ugly columns
bind_cols(trial[i,] %>% # Bind columns of row i to trial columns
dplyr::select(BirdsID, tod_, time, tdif, heading, sex, month, date, hunting, dist.km, hunting2, diel)) %>%
bind_rows(trial[i,] %>%
mutate(used = 1)) %>% # Bind "used" coords and give it = 1
mutate(strata = paste(i-1, BirdsID, sep = "_")) # New column called strata to keep track
temp[((i-2)*20+1):((i-1)*20),] <- x # Dump all of x into empty "temp" df
}
# end with the indexing temp2
temp2[((j-2)*20+1):((j-1)*20),] <- trial # Dump all of trial into "temp2"
}
Looking for possible help in indexing temp2 to store all random and used locations for each BirdsID. There's 401 animals but each animal has a different number of locations but for each location the same number of random locations are generated (ie, 19). Would appreciate any and all suggestions.
I have solved my own problem. Compiling all the results into temp2
dataframe was solved as followed:
# Create an empty data.frame to hold "random" and "used" points FOR EACH BIRD----
temp2 <- data.frame(matrix(NA, nrow = 20 * ((nrow(dat_sf_utm)) - (length(unique(dat_sf_utm$BirdsID)))),
ncol = 20))
colnames(temp2) <- c("used", "x", "y", "distance", "BirdsID", "tod_", "time",
"tdif", "heading", "sex", "month", "date", "hunting", "dist.km",
"hunting2", "diel", "geometry", "id", "speed", "strata")
for(j in unique(dat_sf_utm$BirdsID)){
trial <- dat_sf_utm %>%
group_by(BirdsID) %>% # Group by BirdsID
filter(BirdsID == j) %>% # filter BirdsID j
bind_cols(do.call(rbind, # Bind cols
(.$geometry)) %>% # Of "geometry"
as_tibble() %>% # And make them a tibble
setNames(c("x", "y")) # And call them xy
)
temp <- data.frame(matrix(NA, nrow = 20 * (nrow(trial)-1), # Make empty df to hold
ncol = 20)) # "random" and "used" locs
colnames(temp) <- c("used", "x", "y", "distance", "BirdsID", "tod_", "time",
"tdif", "heading", "sex", "month", "date", "hunting", "dist.km",
"hunting2", "diel", "geometry", "id", "speed", "strata")
for(i in 2:nrow(trial)){
x <- trial[i,] %>% # Take first row i of BirdsID j
ungroup() %>% # Ungroup the df
st_buffer(., 20000) %>% # Buffer that point by 20 km
st_intersection(., st_as_sf(water_poly)) %>% # Intersect the buffer by water polygon
st_sample(., 19, type = "random", exact = TRUE) %>% # Create 19 random points w/in buffer
st_cast(., "POINT") %>% # Make multipoint into point
as(., "Spatial") %>% # Then make it spatialpoints
as.data.frame(.) %>% # Then make it dataframe
mutate(used = 0, # Create column used and give randoms = 0
x = lon, # Get rid of ugly column coords
y = lat, # Calculate euclidean distance below
distance = sqrt((lon - trial$x[i-1])^2 + (lat - trial$y[i-1])^2)) %>%
dplyr::select(-lon, -lat) %>% # Officially get rid of ugly columns
bind_cols(trial[i,] %>% # Bind columns of row i to trial columns
dplyr::select(BirdsID, tod_, time, tdif, heading, sex, month, date, hunting, dist.km, hunting2, diel)) %>%
bind_rows(trial[i,] %>%
mutate(used = 1)) %>% # Bind "used" coords and give it = 1
mutate(strata = paste(i-1, BirdsID, sep = "_")) # New column called strata to keep track
temp[((i-2)*20+1):((i-1)*20),] <- x # Dump all of x into empty "temp" df
}
# end with the indexing temp2
temp2[first(which(is.na(temp2$used))):(first(which(is.na(temp2$used))) + nrow(temp)-1),] <- temp