Округление столбца значений до ближайших значений в другом столбце (код R) - PullRequest
0 голосов
/ 18 апреля 2020

У меня есть фрейм данных с координатами, похожим на приведенный ниже.

longitude latitude
1    95.93604 41.25908
2    95.93371 41.25941
3    95.93137 41.25974
4    95.92904 41.26008
5    95.92670 41.26041

, и я хочу округлить значения долготы и широты до ближайших значений в существующем фрейме данных с координатами, подобными приведенным ниже.

latitude longitude
41.45131  96.42024
40.81344  96.66093
41.11293 102.85215
40.37834  96.61095
42.84468  97.40045
41.18000  96.11592
40.69164  99.53231
40.37834  96.61095
41.34500  95.95712

Как я могу сделать это в R? Я попытался использовать функцию interp1 из пакета pracma, но мне не удалось получить правильный результат. Я полагаю, что мог бы написать свою собственную функцию, но мне также любопытно, есть ли более простой и элегантный способ сделать это. Если у вас есть какие-либо другие предложения относительно того, как я могу найти наиболее близкие соответствующие координаты от одного фрейма данных к другому, это также будет оценено! Спасибо!

Ответы [ 2 ]

0 голосов
/ 18 апреля 2020

Более простой подход (функция действительно).

#' title, Find nearest value
#'
#' @param x, element for which nearest value has to be found.
#' @param ref_col, field name from reference table from which x has to be compared.
#'
#' @return, nearest value to x.
find_nearest_fun <- function(x, ref_col = "latitude") {
  #browser()
  ref_field_vec <- ref_d[[ref_col]] # reference field 
  min_idx <- which.min(abs(ref_field_vec - x)) 
  return(ref_field_vec[min_idx])
}

d %>% mutate(nearest_lat = map_dbl(latitude, ~find_nearest_fun(.x)),
             nearest_long = map_dbl(longitude, ~find_nearest_fun(.x,ref_col = "longitude"))) %>% 
  view()

Данные ( немного изменен для проверки функциональности )

tribble(~latitude, ~longitude,
41.45131,  96.42024,
40.81344,  96.66093,
41.11293,  102.85215,
40.37834,  96.61095,
42.84468,  97.40045,
41.18000,  96.11592,
40.69164,  99.53231,
40.37834,  96.61095,
41.34500,  95.95712
) -> ref_d


tribble(~longitude ,~latitude,
95.93604  ,41.25908,
95.93371  ,41.25941,
95.93137  ,41.25974,
95.92904  ,41.26008,
95.92670  ,41.26041,
98.92670  ,40.26041,
96.92670  ,40.60412
) -> d
0 голосов
/ 18 апреля 2020

Мы можем использовать алгоритм классификации *1001* k-ближайших соседей.

Пакет class имеет функцию knn1, которая может сделать это. Он возвращает индексы ближайших соседей на основе двух фреймов данных, train (данные, содержащие ваши "округленные" координаты) и test (ваши фактические данные).

(ind <- knn1(train, test, cl=1:nrow(train)))
[1] 1 9 9 3 9
Levels: 1 2 3 4 5 6 7 8 9

Это показывает, что первый ряд test ближайший к первому ряду train, четвертый ряд ближайший к третьему ряду и все остальные ряды, ближайший к последней (9-й) строке.

Затем мы можем использовать эти индексы извлекать округленные координаты в два новых столбца (или заменить существующие).

test$longitude.rnd <- train$longitude[ind]
test$latitude.rnd <- train$latitude[ind]
test
  longitude latitude longitude.rnd latitude.rnd
1  96.42604 41.45908      96.42024     41.45131
2  95.93371 41.25941      95.95712     41.34500
3  95.93137 41.25974      95.95712     41.34500
4 102.82904 41.16008     102.85215     41.11293
5  95.92670 41.26041      95.95712     41.34500

Тестовые данные : (Я изменил две строки, чтобы показать изменение, в противном случае все строки вернет 9-е)

test <- structure(list(longitude = c(96.42604, 95.93371, 95.93137, 102.82904, 
95.9267), latitude = c(41.45908, 41.25941, 41.25974, 41.16008, 
41.26041)), row.names = c("1", "2", "3", "4", "5"), class = "data.frame")

  longitude latitude
1  96.42604 41.45908
2  95.93371 41.25941
3  95.93137 41.25974
4 102.82904 41.16008
5  95.92670 41.26041

Данные поезда : (без изменений, за исключением того, что я поменял местами столбцы в соответствии с данными теста)

train <- structure(list(longitude = c(96.42024, 96.66093, 102.85215, 96.61095, 
97.40045, 96.11592, 99.53231, 96.61095, 95.95712), latitude = c(41.45131, 
40.81344, 41.11293, 40.37834, 42.84468, 41.18, 40.69164, 40.37834, 
41.345)), class = "data.frame", row.names = c(NA, -9L))

  longitude latitude
1  96.42024 41.45131
2  96.66093 40.81344
3 102.85215 41.11293
4  96.61095 40.37834
5  97.40045 42.84468
6  96.11592 41.18000
7  99.53231 40.69164
8  96.61095 40.37834
9  95.95712 41.34500
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...