繁体   English   中英

将一列值四舍五入到另一列中最接近的值(R 代码)

[英]Rounding a column of values to the nearest values in another column (R Code)

我有一个坐标数据框,如下所示。

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 中执行此操作? 我尝试使用 package pracma 中的 interp1 function,但我无法获得正确的结果。 我想我可以自己写一个 function,但我也很好奇是否有更简单、更优雅的方法来解决这个问题。 如果您对我如何找到从一个数据帧到另一个数据帧最近的对应坐标有任何其他建议,那也将不胜感激! 谢谢!

我们可以使用k-最近邻分类算法。

class package 具有可以执行此操作的knn1 function。 它根据两个数据框返回最近邻居的索引, 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

一种更简单的方法(确实是 function)。

#' 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM