我正在尝试根据任意列列表计算欧几里德距离。我尝试这样做来计算
dt
中的观测值与 x
中的单个观测值之间的距离。这似乎按预期计算,但我在第 4 行收到警告,因为我没有按引用分配。
dt <- data.table(a=1:10, b=11:20, c=21:30)
x <- data.table(a=5, b=6, c=7)
for(i in names(dt)){
dt[[i]] <- (dt[[i]] - x[1][[i]])^2
}
dt[, euclid := rowSums(.SD), .SDcols=names(dt)]
dt[, euclid := sqrt(euclid)]
然后我将第 4 行替换为
setattr(dt, i, (dt[[i]] - x[1][[i]])^2)
但实际上它并没有更新列。
我可能误解了
setattr()
的工作原理。我认为以下两行是等效的,但显然不是。
dt[, foo := 2]
setattr(dt, "foo", 2)
我欢迎任何关于如何更好地做到这一点的想法和建议。
我有data.table v1.15.4
这是一种不更改原始列值的方法
cbind(dt,
dt[, lapply(names(.SD), \(i) (.SD[,get(i)] - x[,get(i)])^2)][
, .(euclid = sqrt(rowSums(.SD)))])
a b c euclid
<int> <int> <int> <num>
1: 1 11 21 15.39480
2: 2 12 22 16.43168
3: 3 13 23 17.57840
4: 4 14 24 18.81489
5: 5 15 25 20.12461
6: 6 16 26 21.49419
7: 7 17 27 22.91288
8: 8 18 28 24.37212
9: 9 19 29 25.86503
10: 10 20 30 27.38613
有这样的事吗?
dt[, euclid := sqrt(rowSums(mapply(function(a, b) (a-b)^2, .SD, x)))]
# a b c euclid
# <int> <int> <int> <num>
# 1: 1 11 21 15.39480
# 2: 2 12 22 16.43168
# 3: 3 13 23 17.57840
# 4: 4 14 24 18.81489
# 5: 5 15 25 20.12461
# 6: 6 16 26 21.49419
# 7: 7 17 27 22.91288
# 8: 8 18 28 24.37212
# 9: 9 19 29 25.86503
# 10: 10 20 30 27.38613