Я пытаюсь вычислить евклидово расстояние на основе произвольного списка столбцов. Я попытался сделать это, чтобы вычислить расстояние между наблюдениями в 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
Что-то вроде этого?
cols <- c("a", "b", "c")
dt[, euclid := sqrt(rowSums(mapply(function(a, b) (a-b)^2,
.SD, x[, .SD, .SDcols = cols]))),
.SDcols = cols]
# 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
Кажется, что немного Inception нужно использовать x[, .SD]
внутри dt[, ...]
...
Спасибо. Определенно я впервые вижу x[, .SD]
внутри dt[,..]
:-)
Наверное, ты можешь попробовать это
> dt[, euclid := sqrt(rowSums((.SD - unlist(x)[col(.SD)])^2))][]
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(colSums((t(.SD) - unlist(x))**2))][]
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
setattr
устанавливает атрибуты объекта, а не обновляет значения, вы думаете оdata.table::set
для этого? (Не то чтобы я думаю, что это правильный путь, если честно)