I require an efficient approach in R to identify clusters of points using the following rule sets:
- 2 or more points within 2 hours of each other should be clustered.
- Clusters that are within 150m each other (closest point to closest point) and within a 6 day time-window should be combined into larger clusters.
IndividualID represents unique individuals. Clusters between individuals should not be linked.
Ideal output would be a table with a "cluster" column identifying which cluster each point record is linked to.
I've figured out how to address rule set 1, albeit fairly long-winded, so can provide this if needed.
Example data set below:
structure(list(IndividualID = c("P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40", "P_F_3071_40",
"P_F_3071_40", "P_F_3071_40", "P_F_3071_65", "P_F_3071_65", "P_F_3071_65",
"P_F_3071_65", "P_F_3071_65", "P_F_3071_65", "P_F_3071_65", "P_F_3071_65",
"P_F_3071_65", "P_F_3071_65", "P_F_3071_65", "P_F_3071_65", "P_F_3071_65",
"P_F_3071_65", "P_F_3071_65", "P_F_3071_65", "P_F_3071_65", "P_F_3071_65",
"P_F_3071_65", "P_F_3071_65", "P_F_3071_65", "P_F_3071_65", "P_F_3071_65",
"P_F_3071_65", "P_F_3071_65", "P_F_3071_65"), DateTime = structure(c(1460091660,
1462683660, 1465426860, 1465434000, 1465462860, 1465470000, 1465491660,
1465498800, 1465527660, 1465534800, 1465570860, 1465578000, 1465621260,
1465628400, 1465765260, 1465772400, 1465902060, 1465909200, 1465945260,
1465952400, 1465959660, 1465966800, 1465981260, 1465988400, 1466060460,
1466067600, 1466089260, 1466096400, 1466118060, 1466125200, 1466132460,
1466139600, 1466168460, 1466175600, 1466204460, 1466211600, 1466902860,
1466910000, 1466938860, 1466946000, 1466974860, 1466982000, 1467075660,
1467082800, 1467738060, 1467745200, 1467788460, 1467795600, 1467910860,
1467918000, 1468177320, 1468184460, 1468220520, 1468227600, 1468429260,
1468436400, 1468515660, 1468522800, 1468609320, 1468616400, 1468630860,
1468638000, 1468789260, 1468796400, 1468947660, 1468954800, 1468969260,
1468976400, 1468983660, 1468990800, 1469120460, 1469127600, 1469214060,
1469221200, 1469322060, 1469329200, 1469358060, 1469365200, 1469458860,
1469466000, 1469559660, 1469566800, 1469696460, 1469703600, 1469833200,
1469840340, 1469934060, 1469941200, 1469984460, 1469991600), tzone = "", class = c("POSIXct",
"POSIXt")), X = c(-122.3724041, -122.3733317, -122.3714029, -122.3715247,
-122.3750655, -122.3708959, -122.3794764, -122.3829663, -122.4067149,
-122.4112984, -122.409014, -122.408943, -122.4090122, -122.4107643,
-122.4203011, -122.4092476, -122.4094697, -122.4089489, -122.4089616,
-122.4088741, -122.408935, -122.4089612, -122.4086532, -122.4037183,
-122.4201475, -122.4199123, -122.4204426, -122.4202226, -122.4199262,
-122.4199871, -122.4199125, -122.4201827, -122.3938207, -122.3938583,
-122.3918668, -122.3916721, -122.3529901, -122.354418, -122.340651,
-122.3403595, -122.3409872, -122.3380352, -122.3035277, -122.3033569,
-122.3746217, -122.3747383, -122.3770923, -122.3898683, -122.3840227,
-122.3859436, -122.3708576, -122.363574, -122.3885722, -122.3745535,
-122.3246823, -122.3409753, -122.3701529, -122.361142, -122.3611454,
-122.3611205, -122.3428932, -122.3283405, -122.3245829, -122.3245331,
-122.3144215, -122.3141788, -122.3372718, -122.3611578, -122.3611221,
-122.3612322, -122.408749, -122.409146, -122.4087486, -122.3990234,
-122.3866925, -122.3811472, -122.3754158, -122.3750234, -122.386714,
-122.3874818, -122.3786127, -122.3831537, -122.3999038, -122.3986496,
-122.3946552, -122.3944709, -122.394583, -122.3945822, -122.3937728,
-122.3943946), Y = c(43.50910633, 43.50315059, 43.50424753, 43.50443729,
43.50175542, 43.50423574, 43.50466981, 43.50695777, 43.50098758,
43.50792655, 43.5341171, 43.53378358, 43.53429718, 43.53357688,
43.53801069, 43.53427138, 43.53434456, 43.53444992, 43.53441397,
43.53450356, 43.53460292, 43.53444999, 43.53431333, 43.53272097,
43.48167926, 43.48170508, 43.48186084, 43.48158959, 43.48154307,
43.48164243, 43.48168707, 43.48187753, 43.5027298, 43.50267598,
43.50390799, 43.50481638, 43.45381077, 43.46481313, 43.47805195,
43.47983312, 43.48238496, 43.48093622, 43.44715413, 43.44695499,
43.45725372, 43.45673211, 43.45498911, 43.4665025, 43.47118042,
43.47318071, 43.50434358, 43.48172953, 43.46630649, 43.45667707,
43.46522666, 43.48347441, 43.50431268, 43.5036414, 43.50448782,
43.50450569, 43.47423803, 43.4642037, 43.46527109, 43.46529781,
43.50897145, 43.50854679, 43.51569729, 43.50448789, 43.50435262,
43.50447029, 43.46999632, 43.4698543, 43.47003233, 43.49949772,
43.53845663, 43.53727421, 43.53016573, 43.5334051, 43.51679257,
43.51550008, 43.52736482, 43.53349428, 43.49303727, 43.49852329,
43.50586771, 43.50574067, 43.50566923, 43.50575027, 43.50627723,
43.50595637)), row.names = c(NA, -90L), groups = structure(list(
IndividualID = c("P_F_3071_40", "P_F_3071_65"), .rows = structure(list(
1:64, 65:90), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), row.names = c(NA, -2L), class = c("tbl_df",
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"))
igraph
to get connected components from the corresponding graph....