data.table函数内匹配报错:如何修正邻接ID距离过滤逻辑?
问题修正:data.table中邻接ID的切比雪夫距离过滤
问题场景
我有一个data.table,每行对应一个ID,包含该ID的X、Y坐标及多列邻接ID(邻接ID指向表内其他行观测)。目标是将与当前ID切比雪夫距离超过10的邻接ID设为NA,但当前代码运行时报错:
match.SD is not found in calling scope and it is not a column name either. When the first argument inside DT[...] is a single symbol (e.g., DT[var]), data.table looks for var in calling scope
附原代码:
# 更新函数 update_columns <- function(dt, columns_to_update) { for (col in columns_to_update) { dt[, (col) := ifelse(chebyshev_distance(x,y, dt.nearest_neighbours[match.SD, c("x", "y"), on="id"]) > 10, NA, dt[[col]])] } return(dt.nearest_neighbours) } # 切比雪夫距离函数 chebyshev_distance <- function(x1, y1, data) { pmax(abs(x1-data$x), abs(y1-data$y)) } # 模拟数据 dt.nearest_neighbours <- data.table( id = c(1,2,3,4), # ID x = c(10, 20, 30, 40), # X坐标 y = c(5, 10,25,5), # Y坐标 V1 = c(2,3,2,1), # 邻接ID(指向表内其他ID) V2 = c(4,1,4,2), # 第二个邻接ID V3 = c(3,1,1,3) # 第三个邻接ID )
错误原因
match.SD不是data.table的合法语法,原代码的ID匹配逻辑完全错误。- 函数内部直接引用全局变量
dt.nearest_neighbours,未使用传入的参数dt,不符合函数封装逻辑。 - 切比雪夫距离的计算未针对每行邻接ID做对应匹配,会导致维度不匹配问题。
修正方案
步骤1:优化匹配与计算逻辑
利用data.table的连接特性,将邻接ID与对应坐标匹配,直接在表内计算距离并过滤。
修正后的完整代码
library(data.table) # 模拟数据 dt.nearest_neighbours <- data.table( id = c(1,2,3,4), x = c(10, 20, 30, 40), y = c(5, 10,25,5), V1 = c(2,3,2,1), V2 = c(4,1,4,2), V3 = c(3,1,1,3) ) # 修正后的更新函数 update_columns <- function(dt, columns_to_update) { # 提取ID-坐标映射表,用于后续匹配 coord_map <- dt[, .(id, x, y)] for (col in columns_to_update) { # 匹配邻接ID对应的坐标,生成临时列 dt[coord_map, on = paste0(col, "==id"), `:=`(temp_x = i.x, temp_y = i.y)] # 计算切比雪夫距离,超过10则将邻接ID设为NA dt[, (col) := ifelse(pmax(abs(x - temp_x), abs(y - temp_y)) > 10, NA, get(col))] # 删除临时列 dt[, c("temp_x", "temp_y") := NULL] } return(dt) } # 执行更新操作 updated_dt <- update_columns(dt.nearest_neighbours, columns_to_update = c("V1", "V2", "V3")) print(updated_dt)
代码解释
coord_map提取ID与坐标的映射关系,避免重复调用原表。- 通过
on = paste0(col, "==id")将当前邻接列的ID与坐标表的id匹配,获取对应邻接ID的坐标。 - 用
pmax(abs(x - temp_x), abs(y - temp_y))计算切比雪夫距离,超过阈值10时将邻接ID设为NA。 - 最后删除临时生成的坐标列,保持表结构整洁。
运行结果
id x y V1 V2 V3 1: 1 10 5 2 NA 3 2: 2 20 10 3 1 NA 3: 3 30 25 NA NA NA 4: 4 40 5 NA NA NA
内容的提问来源于stack exchange,提问作者TvCasteren
相关产品推荐
相关产品推荐

