for loop indexing to store results in R...generic indexing help for spatial GPS data?

38 Views Asked by At

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.

1

There are 1 best solutions below

0
On BEST ANSWER

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