r - Measuring shortest distance between animal locations and renewable energy (temporal accuracy needed) - Stack Overflow

I have created two sf objects, one for animal locations, and one for turbine locations. The Turbine_sf

I have created two sf objects, one for animal locations, and one for turbine locations. The Turbine_sf includes construction start and stop dates, along with operation dates for each structure.

What I am attempting to do is filter turbine construction/operation dates based on each animal's timestamps (DateTime in pronghorn_sf. I wouldd like to measure the distance to the nearest turbine under construction for each animal location in pronghorn_sf.

I have included my attempt below, which seems to only measure distance for odd numbered rows (cp. picture), rather than date matching animal timestamps and turbine construction periods.

Attempt

# ensure the sf objects are using the same crs
pronghorn_sf <- st_transform(pronghorn_sf, st_crs(Turbine_sf))

# create distance columns using a vectorized approach
pronghorn_sf$construction_distance1 <- apply(st_coordinates(pronghorn_sf), 1, function(coords) {
  current_date <- pronghorn_sf$DateTime[which(st_coordinates(pronghorn_sf) == coords)]
  
  # filter turbines under construction during a pronghorn location's timestamp
  turbines_under_construction <- Turbine_sf %>%
    filter(current_date >= Phase1_Construction_Start_Date & current_date <= Phase1_Construction_End_Date)
  
  if (nrow(turbines_under_construction) > 0) {
    # calculate the distance only if relevant turbines exist
    min(st_distance(st_sfc(st_point(coords), crs = st_crs(Turbine_sf)), turbines_under_construction))
  } else {
    NA
  }
})

which gives

Data

  1. 25 rows of pronghorn_sf:
    > dput(pronghorn_sf1)
    structure(list(AID = structure(c(137L, 137L, 137L, 137L, 137L, 
    137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 139L, 
    139L, 139L, 139L, 139L, 139L, 139L, 139L, 139L, 139L), levels = c("BH_002", 
    "BH_003", "BH_004", "BH_005", "BH_006", "BH_007", "BH_008", "BH_009", 
    "BH_010", "BH_011", "BH_012", "BH_013", "BH_014", "BH_015", "BH_016", 
    "BH_017", "BH_019", "BH_020", "BH_021", "BH_022", "BH_024", "BH_025", 
    "BH_026", "BH_028", "BH_029", "BH_030", "BH_031", "BH_033", "BH_035", 
    "BH_036", "BH_037", "BH_038", "BH_039", "BH_040", "BH_041", "BH_042", 
    "BH_043", "BH_044", "BH_046", "BH_047", "BH_048", "BH_049", "BH_051", 
    "BH_052", "BH_053", "BH_054", "BH_055", "BH_056", "BH_057", "BH_058", 
    "SB_001", "SB_002", "SB_004", "SB_006", "SB_007", "SB_008", "SB_009", 
    "SB_010", "SB_011", "SB_012", "SB_014", "SB_015", "SB_016", "SB_017", 
    "SB_018", "SB_019", "SB_020", "SB_021", "SB_022", "SB_024", "SB_025", 
    "SB_028", "SB_029", "SB_031", "SB_032", "SB_033", "SB_034", "SB_035", 
    "SB_036", "SB_037", "SB_038", "SB_039", "SB_040", "SB_041", "SB_043", 
    "SB_044", "SB_045", "SB_046", "SB_047", "SB_049", "SB_052", "SB_053", 
    "SB_054", "SB_055", "SB_056", "SB_057", "SB_058", "SB_059", "SB_060", 
    "SB_061", "SB_062", "SB_063", "SB_064", "SB_065", "SB_067", "SB_068", 
    "SB_069", "SB_070", "SB_071", "SB_072", "SB_074", "SB_075", "SB_076", 
    "SB_077", "SB_078", "SB_079", "SB_080", "SB_081", "SB_083", "SB_084", 
    "SB_085", "SB_086", "SB_087", "SB_088", "SB_089", "SB_090", "SB_091", 
    "SB_092", "SB_093", "SB_094", "SB_095", "SB_096", "SB_097", "SB_098", 
    "SB_099", "SB_100", "SB_101", "SB_102", "SB_103", "SB_104", "SB_105", 
    "SB_106", "SB_108", "SB_109", "SB_110", "SB_111", "SB_112", "SB_113", 
    "SB_114", "SB_115", "SB_116", "SB_117", "SB_118", "SB_119", "SB_120", 
    "SB_121", "SB_122", "SB_123", "SB_124", "SB_125", "SB_126", "SB_127", 
    "SB_128", "SB_130", "SB_131", "SB_132", "SB_133", "SB_134", "SB_136", 
    "SB_137", "SB_138", "SB_139", "SB_140", "SB_141", "SB_143", "SB_146", 
    "SB_147", "SB_148", "SB_150", "SB_152", "SB_153", "SB_154", "SB_155", 
    "SB_156", "SB_157", "SB_158", "SB_159", "SB_160", "SB_161", "SB_162", 
    "SB_163", "SB_165", "SB_166", "SB_167", "SB_168", "SB_169", "SB_171", 
    "SB_172", "SB_174", "SB_175", "SB_176", "SB_180", "SB_181", "SB_182", 
    "SB_183", "SB_184", "SB_185", "SB_186", "SB_187", "SB_188", "SB_189", 
    "SB_190", "SB_191", "SB_192", "SB_193", "SB_194", "SB_195", "SB_196", 
    "SB_202", "SB_205", "SB_210", "SB_211", "SB_212", "SB_213", "SB_214", 
    "SB_215", "SB_216", "SB_217", "SB_218", "SB_219", "SB_220", "SB_221", 
    "SB_222", "SB_223", "SB_224", "SB_225", "SB_226", "SB_227", "SB_228", 
    "SB_230", "SB_231", "SB_232", "SB_233", "SB_234", "SB_235", "SB_236", 
    "SB_237", "SB_238", "SB_240", "SB_241", "SB_243", "SB_244", "SB_245", 
    "SB_246", "SB_247", "SB_248"), class = "factor"), DateTime = structure(c(1671854437, 
    1671868837, 1671883237, 1671897642, 1671912037, 1671926437, 1671940837, 
    1671955242, 1671969644, 1671984058, 1671998437, 1672012837, 1672027237, 
    1672041646, 1672056037, 1567447242, 1567454404, 1567461604, 1567468803, 
    1567476091, 1567483204, 1567490404, 1567497609, 1567612804, 1567620058
    ), class = c("POSIXct", "POSIXt"), tzone = "UTC"), YNorthing = c(4640831.29, 
    4640687.169, 4642397.708, 4644840.306, 4646350.756, 4646919.927, 
    4646534.687, 4646865.79, 4647306.727, 4647076.159, 4649330.737, 
    4649855.958, 4649766.786, 4650129.319, 4650288.699, 4650026, 
    4649935, 4650148, 4650218, 4650226, 4650345, 4650342, 4650351, 
    4650040, 4649923), XEasting = c(13424219.597, 13425259.957, 13417594.318, 
    13415562.718, 13416285.702, 13415025.005, 13414998.247, 13415298.28, 
    13415021.033, 13416268.994, 13416506.255, 13416930.762, 13417068.436, 
    13417213.538, 13416885.97, 429788, 429323, 429119, 429078, 428974, 
    428886, 428883, 429023, 429870, 429600), x = c(424219.594584907, 
    425259.960358151, 417594.314800596, 415562.71890358, 416285.698693028, 
    415025.006157442, 414998.250352198, 415298.279154033, 415021.035323201, 
    416268.994737265, 416506.253844386, 416930.762803482, 417068.435627463, 
    417213.538974703, 416885.968245001, 429788.134621699, 429322.978335433, 
    429118.858664836, 429078.310284856, 428973.536615617, 428885.689295124, 
    428882.513327488, 429023.407508244, 429870.020439793, 429599.915982921
    ), y = c(4640831.28886158, 4640687.163379, 4642397.70379822, 
    4644840.30088953, 4646350.75440094, 4646919.92935201, 4646534.68665156, 
    4646865.79303352, 4647306.72834182, 4647076.15648437, 4649330.73207423, 
    4649855.95795628, 4649766.78705397, 4650129.32171694, 4650288.69561457, 
    4650026.21325154, 4649935.33876174, 4650147.91029761, 4650217.82758664, 
    4650226.20503632, 4650344.90043192, 4650342.04521013, 4650351.29340809, 
    4650039.8382759, 4649922.70138309), geometry = structure(list(
        structure(c(-105.9138196, 41.9157991), class = c("XY", "POINT", 
        "sfg")), structure(c(-105.9012573, 41.9146003), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.9939202, 41.9292418), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0187703, 41.9510235), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0102634, 41.9647027), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0255573, 41.9696934), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0258245, 41.9662213), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0222519, 41.9692353), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0256611, 41.9731762), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0105682, 41.9712334), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0080253, 41.9915617), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0029752, 41.9963364), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0013006, 41.9955479), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.9996, 41.9988279), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0035772, 42.0002286), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.847774, 41.999121), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.853379, 41.998261), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.855869, 42.000157), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.856367, 42.000783), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.857633, 42.000849), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.858708, 42.00191), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.858746, 42.001884), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.857046, 42.00198), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.846787, 41.999251), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.850034, 41.998172), class = c("XY", 
        "POINT", "sfg"))), class = c("sfc_POINT", "sfc"), precision = 0, bbox = structure(c(xmin = -106.0258245, 
    ymin = 41.9146003, xmax = -105.846787, ymax = 42.00198), class = "bbox"), crs = structure(list(
        input = "EPSG:4326", wkt = "GEOGCRS[\"WGS 84\",\n    ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n        MEMBER[\"World Geodetic System 1984 (Transit)\"],\n        MEMBER[\"World Geodetic System 1984 (G730)\"],\n        MEMBER[\"World Geodetic System 1984 (G873)\"],\n        MEMBER[\"World Geodetic System 1984 (G1150)\"],\n        MEMBER[\"World Geodetic System 1984 (G1674)\"],\n        MEMBER[\"World Geodetic System 1984 (G1762)\"],\n        MEMBER[\"World Geodetic System 1984 (G2139)\"],\n        ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n            LENGTHUNIT[\"metre\",1]],\n        ENSEMBLEACCURACY[2.0]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"geodetic latitude (Lat)\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"geodetic longitude (Lon)\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    USAGE[\n        SCOPE[\"Horizontal component of 3D system.\"],\n        AREA[\"World.\"],\n        BBOX[-90,-180,90,180]],\n    ID[\"EPSG\",4326]]"), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr = structure(c(AID = 1L, 
    DateTime = 1L, YNorthing = 1L, XEasting = 1L, x = 1L, y = 1L), levels = c("constant", 
    "aggregate", "identity"), class = "factor"), row.names = 145350:145374, class = c("sf", 
    "data.frame"))
  1. 50 rows of Turbine_sf1:
    > dput(Turbine_sf1)
    structure(list(name = c("Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Ekola Flats", 
    "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", 
    "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", 
    "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", 
    "Ekola Flats"), pronghorn_overlap = c("Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes"), Phase1_Construction_Start_Date = structure(c(13977, 
    13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 
    13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 
    13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 
    13977, 13977, 13977, 13977, 13977, 13977, 18044, 18044, 18044, 
    18044, 18044, 18044, 18044, 18044, 18044, 18044, 18044, 18044, 
    18044, 18044, 18044, 18044, 18044), class = "Date"), Phase1_Construction_End_Date = structure(c(14183, 
    14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 
    14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 
    14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 
    14183, 14183, 14183, 14183, 14183, 14183, 18261, 18261, 18261, 
    18261, 18261, 18261, 18261, 18261, 18261, 18261, 18261, 18261, 
    18261, 18261, 18261, 18261, 18261), class = "Date"), Phase2_Construction_Start_Date = structure(c(NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, 18322, 18322, 18322, 18322, 18322, 18322, 18322, 18322, 18322, 
    18322, 18322, 18322, 18322, 18322, 18322, 18322, 18322), class = "Date"), 
        Phase2_Construction_End_Date = structure(c(NA, NA, NA, NA, 
        NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
        NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
        18551, 18551, 18551, 18551, 18551, 18551, 18551, 18551, 18551, 
        18551, 18551, 18551, 18551, 18551, 18551, 18551, 18551), class = "Date"), 
        Phase3_Construction_Start_Date = structure(c(NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_), class = "Date"), Phase3_Construction_End_Date = structure(c(NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_), class = "Date"), Operation_Date = structure(c(14232, 
        14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 
        14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 
        14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 
        14232, 14232, 14232, 14232, 14232, 14232, 18611, 18611, 18611, 
        18611, 18611, 18611, 18611, 18611, 18611, 18611, 18611, 18611, 
        18611, 18611, 18611, 18611, 18611), class = "Date"), Operation_End_Date = structure(c(NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_), class = "Date"), Second_Operation_Start_Date = structure(c(NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_), class = "Date"), Second_Operation_End_Date = structure(c(NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_), class = "Date"), geometry = structure(list(
            structure(c(-106.38279, 41.957691), class = c("XY", "POINT", 
            "sfg")), structure(c(-106.434891, 41.971191), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.411491, 41.946693), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.37899, 41.919693), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.365585, 41.945694), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.43399, 41.969692), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.426491, 41.957592), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.412491, 41.959293), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.411591, 41.948292), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.372787, 41.940292), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.366089, 41.926693), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.41259, 41.943092), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.377586, 41.917091), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.412888, 41.956093), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.383286, 41.950592), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.366592, 41.921993), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.36599, 41.928093), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.411987, 41.957592), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.425591, 41.962013), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.411888, 41.952991), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.366089, 41.923393), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.365585, 41.952194), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.425591, 41.959091), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.435486, 41.962193), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.372787, 41.936092), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.420792, 41.971294), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.372787, 41.938892), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.383392, 41.947693), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.383369, 41.949146), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.366692, 41.916294), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.382187, 41.927792), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.43399, 41.968094), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.411789, 41.945091), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.366287, 41.956993), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.202492, 41.625603), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.19799, 41.642895), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.291626, 41.913994), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.196388, 41.645935), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.209488, 41.611423), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.202187, 41.628925), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.201286, 41.636032), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.278893, 41.941605), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.355293, 41.963017), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.328705, 41.919952), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.341125, 41.919991), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.205193, 41.618633), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.328712, 41.923618), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.250381, 41.917053), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.253632, 41.919395), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.341705, 41.923336), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.207588, 41.615055), class = c("XY", 
            "POINT", "sfg"))), class = c("sfc_POINT", "sfc"), precision = 0, bbox = structure(c(xmin = -106.435486, 
        ymin = 41.611423, xmax = -106.196388, ymax = 41.971294), class = "bbox"), crs = structure(list(
            input = "EPSG:4326", wkt = "GEOGCRS[\"WGS 84\",\n    ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n        MEMBER[\"World Geodetic System 1984 (Transit)\"],\n        MEMBER[\"World Geodetic System 1984 (G730)\"],\n        MEMBER[\"World Geodetic System 1984 (G873)\"],\n        MEMBER[\"World Geodetic System 1984 (G1150)\"],\n        MEMBER[\"World Geodetic System 1984 (G1674)\"],\n        MEMBER[\"World Geodetic System 1984 (G1762)\"],\n        MEMBER[\"World Geodetic System 1984 (G2139)\"],\n        ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n            LENGTHUNIT[\"metre\",1]],\n        ENSEMBLEACCURACY[2.0]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"geodetic latitude (Lat)\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"geodetic longitude (Lon)\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    USAGE[\n        SCOPE[\"Horizontal component of 3D system.\"],\n        AREA[\"World.\"],\n        BBOX[-90,-180,90,180]],\n    ID[\"EPSG\",4326]]"), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr = structure(c(name = 1L, 
    pronghorn_overlap = 1L, Phase1_Construction_Start_Date = 1L, 
    Phase1_Construction_End_Date = 1L, Phase2_Construction_Start_Date = 1L, 
    Phase2_Construction_End_Date = 1L, Phase3_Construction_Start_Date = 1L, 
    Phase3_Construction_End_Date = 1L, Operation_Date = 1L, Operation_End_Date = 1L, 
    Second_Operation_Start_Date = 1L, Second_Operation_End_Date = 1L
    ), levels = c("constant", "aggregate", "identity"), class = "factor"), row.names = 225:275, class = c("sf", 
    "data.frame"))

I'd like to end up with a new column in the pronghorn_sf object (which I will probably convert to a dataframe or datatable) that includes distance in meters to the nearest turbine under construction. If an animal's timestamp falls outside of turbine construction periods, I'd like to populate those rows with NAs.

I have created two sf objects, one for animal locations, and one for turbine locations. The Turbine_sf includes construction start and stop dates, along with operation dates for each structure.

What I am attempting to do is filter turbine construction/operation dates based on each animal's timestamps (DateTime in pronghorn_sf. I wouldd like to measure the distance to the nearest turbine under construction for each animal location in pronghorn_sf.

I have included my attempt below, which seems to only measure distance for odd numbered rows (cp. picture), rather than date matching animal timestamps and turbine construction periods.

Attempt

# ensure the sf objects are using the same crs
pronghorn_sf <- st_transform(pronghorn_sf, st_crs(Turbine_sf))

# create distance columns using a vectorized approach
pronghorn_sf$construction_distance1 <- apply(st_coordinates(pronghorn_sf), 1, function(coords) {
  current_date <- pronghorn_sf$DateTime[which(st_coordinates(pronghorn_sf) == coords)]
  
  # filter turbines under construction during a pronghorn location's timestamp
  turbines_under_construction <- Turbine_sf %>%
    filter(current_date >= Phase1_Construction_Start_Date & current_date <= Phase1_Construction_End_Date)
  
  if (nrow(turbines_under_construction) > 0) {
    # calculate the distance only if relevant turbines exist
    min(st_distance(st_sfc(st_point(coords), crs = st_crs(Turbine_sf)), turbines_under_construction))
  } else {
    NA
  }
})

which gives

Data

  1. 25 rows of pronghorn_sf:
    > dput(pronghorn_sf1)
    structure(list(AID = structure(c(137L, 137L, 137L, 137L, 137L, 
    137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 137L, 139L, 
    139L, 139L, 139L, 139L, 139L, 139L, 139L, 139L, 139L), levels = c("BH_002", 
    "BH_003", "BH_004", "BH_005", "BH_006", "BH_007", "BH_008", "BH_009", 
    "BH_010", "BH_011", "BH_012", "BH_013", "BH_014", "BH_015", "BH_016", 
    "BH_017", "BH_019", "BH_020", "BH_021", "BH_022", "BH_024", "BH_025", 
    "BH_026", "BH_028", "BH_029", "BH_030", "BH_031", "BH_033", "BH_035", 
    "BH_036", "BH_037", "BH_038", "BH_039", "BH_040", "BH_041", "BH_042", 
    "BH_043", "BH_044", "BH_046", "BH_047", "BH_048", "BH_049", "BH_051", 
    "BH_052", "BH_053", "BH_054", "BH_055", "BH_056", "BH_057", "BH_058", 
    "SB_001", "SB_002", "SB_004", "SB_006", "SB_007", "SB_008", "SB_009", 
    "SB_010", "SB_011", "SB_012", "SB_014", "SB_015", "SB_016", "SB_017", 
    "SB_018", "SB_019", "SB_020", "SB_021", "SB_022", "SB_024", "SB_025", 
    "SB_028", "SB_029", "SB_031", "SB_032", "SB_033", "SB_034", "SB_035", 
    "SB_036", "SB_037", "SB_038", "SB_039", "SB_040", "SB_041", "SB_043", 
    "SB_044", "SB_045", "SB_046", "SB_047", "SB_049", "SB_052", "SB_053", 
    "SB_054", "SB_055", "SB_056", "SB_057", "SB_058", "SB_059", "SB_060", 
    "SB_061", "SB_062", "SB_063", "SB_064", "SB_065", "SB_067", "SB_068", 
    "SB_069", "SB_070", "SB_071", "SB_072", "SB_074", "SB_075", "SB_076", 
    "SB_077", "SB_078", "SB_079", "SB_080", "SB_081", "SB_083", "SB_084", 
    "SB_085", "SB_086", "SB_087", "SB_088", "SB_089", "SB_090", "SB_091", 
    "SB_092", "SB_093", "SB_094", "SB_095", "SB_096", "SB_097", "SB_098", 
    "SB_099", "SB_100", "SB_101", "SB_102", "SB_103", "SB_104", "SB_105", 
    "SB_106", "SB_108", "SB_109", "SB_110", "SB_111", "SB_112", "SB_113", 
    "SB_114", "SB_115", "SB_116", "SB_117", "SB_118", "SB_119", "SB_120", 
    "SB_121", "SB_122", "SB_123", "SB_124", "SB_125", "SB_126", "SB_127", 
    "SB_128", "SB_130", "SB_131", "SB_132", "SB_133", "SB_134", "SB_136", 
    "SB_137", "SB_138", "SB_139", "SB_140", "SB_141", "SB_143", "SB_146", 
    "SB_147", "SB_148", "SB_150", "SB_152", "SB_153", "SB_154", "SB_155", 
    "SB_156", "SB_157", "SB_158", "SB_159", "SB_160", "SB_161", "SB_162", 
    "SB_163", "SB_165", "SB_166", "SB_167", "SB_168", "SB_169", "SB_171", 
    "SB_172", "SB_174", "SB_175", "SB_176", "SB_180", "SB_181", "SB_182", 
    "SB_183", "SB_184", "SB_185", "SB_186", "SB_187", "SB_188", "SB_189", 
    "SB_190", "SB_191", "SB_192", "SB_193", "SB_194", "SB_195", "SB_196", 
    "SB_202", "SB_205", "SB_210", "SB_211", "SB_212", "SB_213", "SB_214", 
    "SB_215", "SB_216", "SB_217", "SB_218", "SB_219", "SB_220", "SB_221", 
    "SB_222", "SB_223", "SB_224", "SB_225", "SB_226", "SB_227", "SB_228", 
    "SB_230", "SB_231", "SB_232", "SB_233", "SB_234", "SB_235", "SB_236", 
    "SB_237", "SB_238", "SB_240", "SB_241", "SB_243", "SB_244", "SB_245", 
    "SB_246", "SB_247", "SB_248"), class = "factor"), DateTime = structure(c(1671854437, 
    1671868837, 1671883237, 1671897642, 1671912037, 1671926437, 1671940837, 
    1671955242, 1671969644, 1671984058, 1671998437, 1672012837, 1672027237, 
    1672041646, 1672056037, 1567447242, 1567454404, 1567461604, 1567468803, 
    1567476091, 1567483204, 1567490404, 1567497609, 1567612804, 1567620058
    ), class = c("POSIXct", "POSIXt"), tzone = "UTC"), YNorthing = c(4640831.29, 
    4640687.169, 4642397.708, 4644840.306, 4646350.756, 4646919.927, 
    4646534.687, 4646865.79, 4647306.727, 4647076.159, 4649330.737, 
    4649855.958, 4649766.786, 4650129.319, 4650288.699, 4650026, 
    4649935, 4650148, 4650218, 4650226, 4650345, 4650342, 4650351, 
    4650040, 4649923), XEasting = c(13424219.597, 13425259.957, 13417594.318, 
    13415562.718, 13416285.702, 13415025.005, 13414998.247, 13415298.28, 
    13415021.033, 13416268.994, 13416506.255, 13416930.762, 13417068.436, 
    13417213.538, 13416885.97, 429788, 429323, 429119, 429078, 428974, 
    428886, 428883, 429023, 429870, 429600), x = c(424219.594584907, 
    425259.960358151, 417594.314800596, 415562.71890358, 416285.698693028, 
    415025.006157442, 414998.250352198, 415298.279154033, 415021.035323201, 
    416268.994737265, 416506.253844386, 416930.762803482, 417068.435627463, 
    417213.538974703, 416885.968245001, 429788.134621699, 429322.978335433, 
    429118.858664836, 429078.310284856, 428973.536615617, 428885.689295124, 
    428882.513327488, 429023.407508244, 429870.020439793, 429599.915982921
    ), y = c(4640831.28886158, 4640687.163379, 4642397.70379822, 
    4644840.30088953, 4646350.75440094, 4646919.92935201, 4646534.68665156, 
    4646865.79303352, 4647306.72834182, 4647076.15648437, 4649330.73207423, 
    4649855.95795628, 4649766.78705397, 4650129.32171694, 4650288.69561457, 
    4650026.21325154, 4649935.33876174, 4650147.91029761, 4650217.82758664, 
    4650226.20503632, 4650344.90043192, 4650342.04521013, 4650351.29340809, 
    4650039.8382759, 4649922.70138309), geometry = structure(list(
        structure(c(-105.9138196, 41.9157991), class = c("XY", "POINT", 
        "sfg")), structure(c(-105.9012573, 41.9146003), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.9939202, 41.9292418), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0187703, 41.9510235), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0102634, 41.9647027), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0255573, 41.9696934), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0258245, 41.9662213), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0222519, 41.9692353), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0256611, 41.9731762), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0105682, 41.9712334), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0080253, 41.9915617), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0029752, 41.9963364), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0013006, 41.9955479), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.9996, 41.9988279), class = c("XY", 
        "POINT", "sfg")), structure(c(-106.0035772, 42.0002286), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.847774, 41.999121), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.853379, 41.998261), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.855869, 42.000157), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.856367, 42.000783), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.857633, 42.000849), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.858708, 42.00191), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.858746, 42.001884), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.857046, 42.00198), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.846787, 41.999251), class = c("XY", 
        "POINT", "sfg")), structure(c(-105.850034, 41.998172), class = c("XY", 
        "POINT", "sfg"))), class = c("sfc_POINT", "sfc"), precision = 0, bbox = structure(c(xmin = -106.0258245, 
    ymin = 41.9146003, xmax = -105.846787, ymax = 42.00198), class = "bbox"), crs = structure(list(
        input = "EPSG:4326", wkt = "GEOGCRS[\"WGS 84\",\n    ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n        MEMBER[\"World Geodetic System 1984 (Transit)\"],\n        MEMBER[\"World Geodetic System 1984 (G730)\"],\n        MEMBER[\"World Geodetic System 1984 (G873)\"],\n        MEMBER[\"World Geodetic System 1984 (G1150)\"],\n        MEMBER[\"World Geodetic System 1984 (G1674)\"],\n        MEMBER[\"World Geodetic System 1984 (G1762)\"],\n        MEMBER[\"World Geodetic System 1984 (G2139)\"],\n        ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n            LENGTHUNIT[\"metre\",1]],\n        ENSEMBLEACCURACY[2.0]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"geodetic latitude (Lat)\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"geodetic longitude (Lon)\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    USAGE[\n        SCOPE[\"Horizontal component of 3D system.\"],\n        AREA[\"World.\"],\n        BBOX[-90,-180,90,180]],\n    ID[\"EPSG\",4326]]"), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr = structure(c(AID = 1L, 
    DateTime = 1L, YNorthing = 1L, XEasting = 1L, x = 1L, y = 1L), levels = c("constant", 
    "aggregate", "identity"), class = "factor"), row.names = 145350:145374, class = c("sf", 
    "data.frame"))
  1. 50 rows of Turbine_sf1:
    > dput(Turbine_sf1)
    structure(list(name = c("Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Seven Mile Hill I & II", 
    "Seven Mile Hill I & II", "Seven Mile Hill I & II", "Ekola Flats", 
    "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", 
    "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", 
    "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", "Ekola Flats", 
    "Ekola Flats"), pronghorn_overlap = c("Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", 
    "Yes", "Yes"), Phase1_Construction_Start_Date = structure(c(13977, 
    13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 
    13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 
    13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 13977, 
    13977, 13977, 13977, 13977, 13977, 13977, 18044, 18044, 18044, 
    18044, 18044, 18044, 18044, 18044, 18044, 18044, 18044, 18044, 
    18044, 18044, 18044, 18044, 18044), class = "Date"), Phase1_Construction_End_Date = structure(c(14183, 
    14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 
    14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 
    14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 14183, 
    14183, 14183, 14183, 14183, 14183, 14183, 18261, 18261, 18261, 
    18261, 18261, 18261, 18261, 18261, 18261, 18261, 18261, 18261, 
    18261, 18261, 18261, 18261, 18261), class = "Date"), Phase2_Construction_Start_Date = structure(c(NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
    NA, 18322, 18322, 18322, 18322, 18322, 18322, 18322, 18322, 18322, 
    18322, 18322, 18322, 18322, 18322, 18322, 18322, 18322), class = "Date"), 
        Phase2_Construction_End_Date = structure(c(NA, NA, NA, NA, 
        NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
        NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
        18551, 18551, 18551, 18551, 18551, 18551, 18551, 18551, 18551, 
        18551, 18551, 18551, 18551, 18551, 18551, 18551, 18551), class = "Date"), 
        Phase3_Construction_Start_Date = structure(c(NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_), class = "Date"), Phase3_Construction_End_Date = structure(c(NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_), class = "Date"), Operation_Date = structure(c(14232, 
        14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 
        14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 
        14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 14232, 
        14232, 14232, 14232, 14232, 14232, 14232, 18611, 18611, 18611, 
        18611, 18611, 18611, 18611, 18611, 18611, 18611, 18611, 18611, 
        18611, 18611, 18611, 18611, 18611), class = "Date"), Operation_End_Date = structure(c(NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_), class = "Date"), Second_Operation_Start_Date = structure(c(NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_), class = "Date"), Second_Operation_End_Date = structure(c(NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
        NA_real_, NA_real_), class = "Date"), geometry = structure(list(
            structure(c(-106.38279, 41.957691), class = c("XY", "POINT", 
            "sfg")), structure(c(-106.434891, 41.971191), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.411491, 41.946693), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.37899, 41.919693), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.365585, 41.945694), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.43399, 41.969692), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.426491, 41.957592), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.412491, 41.959293), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.411591, 41.948292), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.372787, 41.940292), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.366089, 41.926693), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.41259, 41.943092), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.377586, 41.917091), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.412888, 41.956093), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.383286, 41.950592), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.366592, 41.921993), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.36599, 41.928093), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.411987, 41.957592), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.425591, 41.962013), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.411888, 41.952991), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.366089, 41.923393), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.365585, 41.952194), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.425591, 41.959091), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.435486, 41.962193), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.372787, 41.936092), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.420792, 41.971294), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.372787, 41.938892), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.383392, 41.947693), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.383369, 41.949146), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.366692, 41.916294), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.382187, 41.927792), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.43399, 41.968094), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.411789, 41.945091), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.366287, 41.956993), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.202492, 41.625603), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.19799, 41.642895), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.291626, 41.913994), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.196388, 41.645935), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.209488, 41.611423), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.202187, 41.628925), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.201286, 41.636032), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.278893, 41.941605), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.355293, 41.963017), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.328705, 41.919952), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.341125, 41.919991), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.205193, 41.618633), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.328712, 41.923618), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.250381, 41.917053), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.253632, 41.919395), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.341705, 41.923336), class = c("XY", 
            "POINT", "sfg")), structure(c(-106.207588, 41.615055), class = c("XY", 
            "POINT", "sfg"))), class = c("sfc_POINT", "sfc"), precision = 0, bbox = structure(c(xmin = -106.435486, 
        ymin = 41.611423, xmax = -106.196388, ymax = 41.971294), class = "bbox"), crs = structure(list(
            input = "EPSG:4326", wkt = "GEOGCRS[\"WGS 84\",\n    ENSEMBLE[\"World Geodetic System 1984 ensemble\",\n        MEMBER[\"World Geodetic System 1984 (Transit)\"],\n        MEMBER[\"World Geodetic System 1984 (G730)\"],\n        MEMBER[\"World Geodetic System 1984 (G873)\"],\n        MEMBER[\"World Geodetic System 1984 (G1150)\"],\n        MEMBER[\"World Geodetic System 1984 (G1674)\"],\n        MEMBER[\"World Geodetic System 1984 (G1762)\"],\n        MEMBER[\"World Geodetic System 1984 (G2139)\"],\n        ELLIPSOID[\"WGS 84\",6378137,298.257223563,\n            LENGTHUNIT[\"metre\",1]],\n        ENSEMBLEACCURACY[2.0]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"geodetic latitude (Lat)\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"geodetic longitude (Lon)\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    USAGE[\n        SCOPE[\"Horizontal component of 3D system.\"],\n        AREA[\"World.\"],\n        BBOX[-90,-180,90,180]],\n    ID[\"EPSG\",4326]]"), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr = structure(c(name = 1L, 
    pronghorn_overlap = 1L, Phase1_Construction_Start_Date = 1L, 
    Phase1_Construction_End_Date = 1L, Phase2_Construction_Start_Date = 1L, 
    Phase2_Construction_End_Date = 1L, Phase3_Construction_Start_Date = 1L, 
    Phase3_Construction_End_Date = 1L, Operation_Date = 1L, Operation_End_Date = 1L, 
    Second_Operation_Start_Date = 1L, Second_Operation_End_Date = 1L
    ), levels = c("constant", "aggregate", "identity"), class = "factor"), row.names = 225:275, class = c("sf", 
    "data.frame"))

I'd like to end up with a new column in the pronghorn_sf object (which I will probably convert to a dataframe or datatable) that includes distance in meters to the nearest turbine under construction. If an animal's timestamp falls outside of turbine construction periods, I'd like to populate those rows with NAs.

Share Improve this question edited Nov 24, 2024 at 16:09 Friede 8,4512 gold badges9 silver badges29 bronze badges asked Nov 19, 2024 at 21:53 c.rob4c.rob4 133 bronze badges 5
  • 2 Hello and welcome to SO. Please share data as text! Paste the output of dput(Pronghorn_sf) etc into your question. Do not use pictures. Have a read stackoverflow/questions/5963269/… – Friede Commented Nov 19, 2024 at 21:58
  • 1 Thank you for the suggestion, I've added the output to the question. I'll give that link a read, thanks! – c.rob4 Commented Nov 19, 2024 at 23:48
  • 2 That's a good start. We need a relevant sample of turbine as well I suspect. You might want to shorten the sample data to a few lines/rows. Obviously thos should be relevant for one another. – Friede Commented Nov 19, 2024 at 23:54
  • I tried with the data provided in the image for turbine. But this doesn't help. There is nothing left after filtering. – Friede Commented Nov 20, 2024 at 16:56
  • Thank you for the feedback. Yes, I think the observations I included for the turbine sf did not have overlapping dates. I've updated the data in the question. The lines taken from the sf objects above should now have overlapping date data. – c.rob4 Commented Nov 20, 2024 at 20:30
Add a comment  | 

2 Answers 2

Reset to default 1

I believe we can simply this a bit by first moving from POINTs to MULTIPOINTs for turbine locations so we'd have a set of points for each unique construction date range.

From there we can use date ranges and animal observation dates with overlap join to get an sf object with 2 geometry columns, one with POINTs and another with MULTIPOINTs; using those in st_distance() will get us distances from every animal location to the closest turbine that was under construction at that date. Or NA if there were no such turbines.

Following assumes that all dates and DateTime values are in UTC, for data from GPS trackers this is probably true, but construction dates are likely in local timezone. Perhaps something to consider if 6 ... 7-hour difference happens to play a role here.


Turbines aggregated to MULTIPOINTs by construction date ranges:
library(dplyr, warn.conflicts = FALSE)
library(tidyr)
library(sf)

# tranform to a tidy frame with one set of start/end dates and a phase column;
# group by dates (and phase, if needed) and summarise POINTs to MULTIPOINTs
turbine_constr_sf <- 
  Turbine_sf |> 
  select(name, contains("Construction")) |> 
  mutate(id = row_number(), .before = 1) |> 
  pivot_longer(
    contains("Construction"), 
    names_pattern = "Phase(\\d+)_(.*)", 
    names_to = c("phase", "label"), 
    values_drop_na = TRUE
  ) |> 
  pivot_wider(names_from = label) |> 
  # include `phase` in grouping variables if it must be tracked
  summarise(across(geometry, st_union), .by = c(Construction_Start_Date, Construction_End_Date))

turbine_constr_sf
#> Simple feature collection with 3 features and 2 fields
#> Geometry type: MULTIPOINT
#> Dimension:     XY
#> Bounding box:  xmin: -106.4355 ymin: 41.61142 xmax: -106.1964 ymax: 41.97129
#> Geodetic CRS:  WGS 84
#> # A tibble: 3 × 3
#>   Construction_Start_Date Construction_End_Date                                                                                  geometry
#>   <date>                  <date>                                                                                         <MULTIPOINT [°]>
#> 1 2008-04-08              2008-10-31            ((-106.4208 41.97129), (-106.434 41.96809), (-106.434 41.96969), (-106.4349 41.97119),...
#> 2 2019-05-28              2019-12-31            ((-106.3553 41.96302), (-106.2504 41.91705), (-106.3411 41.91999), (-106.3287 41.91995...
#> 3 2020-03-01              2020-10-16            ((-106.3553 41.96302), (-106.2504 41.91705), (-106.3411 41.91999), (-106.3287 41.91995...
Join turbine MULTIPOINTs by date, get distance to the closest under construction turbine :
# join turbine_constr_sf by date range, we'll end up with 2 geometry columns;
# get distances between 2 geometry sets, by elements

pronghorn_sf |> 
  mutate(date = as.Date(DateTime)) |> 
  # sf::left_join.sf() will not accept 2 `sf` objects, 
  # drop sf class but keep (renamed) geom.column
  left_join(
    as.data.frame(turbine_constr_sf) |> select(ends_with("Date"), geom_turbines = geometry),
    by = join_by(between(date, Construction_Start_Date, Construction_End_Date))
  ) |> 
  mutate(construction_distance = st_distance(geometry, geom_turbines, by_element = TRUE)) |> 
  select(-c(date, geom_turbines, matches("Construction.*Date"))) |> 
  print(n = 30)
#> Simple feature collection with 25 features and 7 fields
#> Geometry type: POINT
#> Dimension:     XY
#> Bounding box:  xmin: -106.0258 ymin: 41.9146 xmax: -105.8468 ymax: 42.00198
#> Geodetic CRS:  WGS 84
#>       AID            DateTime YNorthing XEasting        x       y construction_distance                   geometry
#> 1  SB_101 2022-12-24 04:00:37   4640831 13424220 424219.6 4640831                NA [m]  POINT (-105.9138 41.9158)
#> 2  SB_101 2022-12-24 08:00:37   4640687 13425260 425260.0 4640687                NA [m]  POINT (-105.9013 41.9146)
#> 3  SB_101 2022-12-24 12:00:37   4642398 13417594 417594.3 4642398                NA [m] POINT (-105.9939 41.92924)
#> 4  SB_101 2022-12-24 16:00:42   4644840 13415563 415562.7 4644840                NA [m] POINT (-106.0188 41.95102)
#> 5  SB_101 2022-12-24 20:00:37   4646351 13416286 416285.7 4646351                NA [m]  POINT (-106.0103 41.9647)
#> 6  SB_101 2022-12-25 00:00:37   4646920 13415025 415025.0 4646920                NA [m] POINT (-106.0256 41.96969)
#> 7  SB_101 2022-12-25 04:00:37   4646535 13414998 414998.3 4646535                NA [m] POINT (-106.0258 41.96622)
#> 8  SB_101 2022-12-25 08:00:42   4646866 13415298 415298.3 4646866                NA [m] POINT (-106.0223 41.96924)
#> 9  SB_101 2022-12-25 12:00:44   4647307 13415021 415021.0 4647307                NA [m] POINT (-106.0257 41.97318)
#> 10 SB_101 2022-12-25 16:00:58   4647076 13416269 416269.0 4647076                NA [m] POINT (-106.0106 41.97123)
#> 11 SB_101 2022-12-25 20:00:37   4649331 13416506 416506.3 4649331                NA [m]  POINT (-106.008 41.99156)
#> 12 SB_101 2022-12-26 00:00:37   4649856 13416931 416930.8 4649856                NA [m]  POINT (-106.003 41.99634)
#> 13 SB_101 2022-12-26 04:00:37   4649767 13417068 417068.4 4649767                NA [m] POINT (-106.0013 41.99555)
#> 14 SB_101 2022-12-26 08:00:46   4650129 13417214 417213.5 4650129                NA [m] POINT (-105.9996 41.99883)
#> 15 SB_101 2022-12-26 12:00:37   4650289 13416886 416886.0 4650289                NA [m] POINT (-106.0036 42.00023)
#> 16 SB_103 2019-09-02 18:00:42   4650026   429788 429788.1 4650026          34518.99 [m] POINT (-105.8478 41.99912)
#> 17 SB_103 2019-09-02 20:00:04   4649935   429323 429323.0 4649935          34046.96 [m] POINT (-105.8534 41.99826)
#> 18 SB_103 2019-09-02 22:00:04   4650148   429119 429118.9 4650148          33904.87 [m] POINT (-105.8559 42.00016)
#> 19 SB_103 2019-09-03 00:00:03   4650218   429078 429078.3 4650218          33884.16 [m] POINT (-105.8564 42.00078)
#> 20 SB_103 2019-09-03 02:01:31   4650226   428974 428973.5 4650226          33785.52 [m] POINT (-105.8576 42.00085)
#> 21 SB_103 2019-09-03 04:00:04   4650345   428886 428885.7 4650345          33732.64 [m] POINT (-105.8587 42.00191)
#> 22 SB_103 2019-09-03 06:00:04   4650342   428883 428882.5 4650342          33728.82 [m] POINT (-105.8587 42.00188)
#> 23 SB_103 2019-09-03 08:00:09   4650351   429023 429023.4 4650351          33866.76 [m]  POINT (-105.857 42.00198)
#> 24 SB_103 2019-09-04 16:00:04   4650040   429870 429870.0 4650040          34601.49 [m] POINT (-105.8468 41.99925)
#> 25 SB_103 2019-09-04 18:00:58   4649923   429600 429599.9 4649923          34311.15 [m]   POINT (-105.85 41.99817)

If you have partially overlapping construction date ranges in your actual dataset, your row count should increase and you should probably apply another filter to choose between matched multipoints. And if there are so many date range overlaps that resulting row count explodes, this whole approach should probably be reviewed.

We suspect an R-like way to do the fitering is to merge the objects.

You provide objects of class data.frame and sf. We try to avoid merge.sf(), so we explicitly use as.data.frame() which might be the easiest. One reason for this is that merge.sf() accepts only one sf-object. We could further reduce the code if we knew the desired output better.

Assumptions

  1. all dates and datetimes are in UTC
  2. pronghorn_sf and Turbine_sf have the same crs
  3. pronghorns can be uniquely identified by AID

Advice

  1. Select columns of relevance
  2. Use shorter variable names
library(sf)
as.data.frame(pronghorn_sf) |>
  transform(date=as.Date(DateTime, tz="UTC")) |>
  merge(transform(as.data.frame(Turbine_sf), t_id=seq(nrow(Turbine_sf))), by=NULL) |>
  subset(date>=Phase1_Construction_Start_Date & date<=Phase1_Construction_End_Date) |>
  st_as_sf() |> 
  transform(ed=st_distance(geometry.x, geometry.y, by_element=TRUE), 
            AID=droplevels(AID)) |>
  tapply(~AID+DateTime, subset, ed==min(ed)) |> do.call(what="rbind") |>
  as.data.frame() |>
  subset(select=c(AID, DateTime, ed, t_id, name)) |>
  merge(as.data.frame(pronghorn_sf), y=_, by=c("AID", "DateTime"), all.x=TRUE)
      AID            DateTime YNorthing XEasting        x       y                   geometry           ed t_id        name
1  SB_101 2022-12-24 04:00:37   4640831 13424220 424219.6 4640831  POINT (-105.9138 41.9158)       NA [m]   NA        <NA>
2  SB_101 2022-12-24 08:00:37   4640687 13425260 425260.0 4640687  POINT (-105.9013 41.9146)       NA [m]   NA        <NA>
3  SB_101 2022-12-24 12:00:37   4642398 13417594 417594.3 4642398 POINT (-105.9939 41.92924)       NA [m]   NA        <NA>
4  SB_101 2022-12-24 16:00:42   4644840 13415563 415562.7 4644840 POINT (-106.0188 41.95102)       NA [m]   NA        <NA>
5  SB_101 2022-12-24 20:00:37   4646351 13416286 416285.7 4646351  POINT (-106.0103 41.9647)       NA [m]   NA        <NA>
6  SB_101 2022-12-25 00:00:37   4646920 13415025 415025.0 4646920 POINT (-106.0256 41.96969)       NA [m]   NA        <NA>
7  SB_101 2022-12-25 04:00:37   4646535 13414998 414998.3 4646535 POINT (-106.0258 41.96622)       NA [m]   NA        <NA>
8  SB_101 2022-12-25 08:00:42   4646866 13415298 415298.3 4646866 POINT (-106.0223 41.96924)       NA [m]   NA        <NA>
9  SB_101 2022-12-25 12:00:44   4647307 13415021 415021.0 4647307 POINT (-106.0257 41.97318)       NA [m]   NA        <NA>
10 SB_101 2022-12-25 16:00:58   4647076 13416269 416269.0 4647076 POINT (-106.0106 41.97123)       NA [m]   NA        <NA>
11 SB_101 2022-12-25 20:00:37   4649331 13416506 416506.3 4649331  POINT (-106.008 41.99156)       NA [m]   NA        <NA>
12 SB_101 2022-12-26 00:00:37   4649856 13416931 416930.8 4649856  POINT (-106.003 41.99634)       NA [m]   NA        <NA>
13 SB_101 2022-12-26 04:00:37   4649767 13417068 417068.4 4649767 POINT (-106.0013 41.99555)       NA [m]   NA        <NA>
14 SB_101 2022-12-26 08:00:46   4650129 13417214 417213.5 4650129 POINT (-105.9996 41.99883)       NA [m]   NA        <NA>
15 SB_101 2022-12-26 12:00:37   4650289 13416886 416886.0 4650289 POINT (-106.0036 42.00023)       NA [m]   NA        <NA>
16 SB_103 2019-09-02 18:00:42   4650026   429788 429788.1 4650026 POINT (-105.8478 41.99912) 34518.99 [m]   48 Ekola Flats
17 SB_103 2019-09-02 20:00:04   4649935   429323 429323.0 4649935 POINT (-105.8534 41.99826) 34046.96 [m]   48 Ekola Flats
18 SB_103 2019-09-02 22:00:04   4650148   429119 429118.9 4650148 POINT (-105.8559 42.00016) 33904.87 [m]   48 Ekola Flats
19 SB_103 2019-09-03 00:00:03   4650218   429078 429078.3 4650218 POINT (-105.8564 42.00078) 33884.16 [m]   48 Ekola Flats
20 SB_103 2019-09-03 02:01:31   4650226   428974 428973.5 4650226 POINT (-105.8576 42.00085) 33785.52 [m]   48 Ekola Flats
21 SB_103 2019-09-03 04:00:04   4650345   428886 428885.7 4650345 POINT (-105.8587 42.00191) 33732.64 [m]   48 Ekola Flats
22 SB_103 2019-09-03 06:00:04   4650342   428883 428882.5 4650342 POINT (-105.8587 42.00188) 33728.82 [m]   48 Ekola Flats
23 SB_103 2019-09-03 08:00:09   4650351   429023 429023.4 4650351  POINT (-105.857 42.00198) 33866.76 [m]   48 Ekola Flats
24 SB_103 2019-09-04 16:00:04   4650040   429870 429870.0 4650040 POINT (-105.8468 41.99925) 34601.49 [m]   48 Ekola Flats
25 SB_103 2019-09-04 18:00:58   4649923   429600 429599.9 4649923   POINT (-105.85 41.99817) 34311.15 [m]   48 Ekola Flats

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742396227a4435999.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信