Из вашего описания ваши данные выглядят так:
head(df)
# id x y
# 1 ID1 36 29
# 2 ID2 21 27
# 3 ID3 35 13
# 4 ID4 35 21
# 5 ID5 29 29
# 6 ID6 34 27
...
Как вы указали, вы могли бы сделать это проще, если бы ваши данные были в матричном формате. Вы можете легко создать один; он просто должен быть достаточно большим, чтобы вместить ваши максимальные значения x и y, и иметь дополнительную строку и столбец, чтобы вы могли аккуратно разобраться с краями и углами.
Первоначально мы сделаем записи со всеми пустыми строками.
mat <- matrix(rep("", (max(df$x) + 1) * (max(df$y) + 1)), ncol = max(df$x + 1))
Теперь мы можем записать идентификаторы в соответствующие позиции в матрице, используя индексы x и y:
for(i in 1:nrow(df)) mat[df$y[i], df$x[i]] <- as.character(df$id[i])
Теперь найти восемь соседей каждой записи в вашем фрейме данных так же просто, как проверить 8 соседних записей матрицы. Самый простой способ представить это - сохранить исходный фрейм данных и добавить новый столбец для каждого из 8 относительных положений компаса:
df$east <- mat[df$y + nrow(mat) * (df$x - 2)]
df$west <- mat[df$y + nrow(mat) * (df$x)]
df$north <- mat[df$y + 1 + nrow(mat) * (df$x - 1)]
df$south <- mat[df$y - 1 + nrow(mat) * (df$x - 1)]
df$southeast <- mat[df$y - 1 + nrow(mat) * (df$x - 2)]
df$southwest <- mat[df$y - 1 + nrow(mat) * (df$x)]
df$northeast <- mat[df$y + 1 + nrow(mat) * (df$x - 2)]
df$northwest <- mat[df$y + 1 + nrow(mat) * (df$x)]
Теперь у нас есть:
head(df)
# id x y east west north south southeast southwest northeast northwest
# 1 ID1 36 29 ID26 ID317 ID279 ID182
# 2 ID2 21 27 ID178 ID63 ID205 ID97
# 3 ID3 35 13 ID291
# 4 ID4 35 21 ID239 ID338 ID328 ID29
# 5 ID5 29 29 ID268 ID78 ID85
# 6 ID6 34 27 ID20 ID271 ID41 ID154 ID143 ID80 ID72 ID279
Просто чтобы доказать это, мы можем сделать:
df$north[1]
# [1] "ID26"
df$south[which(df$id == "ID26")]
# [1] "ID1"