Ближайшее значение к конкретному столбцу в R
Я хотел бы найти ближайшее значение для столбца х3 ниже.
data=data.frame(x1=c(24,12,76),x2=c(15,30,20),x3=c(45,27,15))
data
x1 x2 x3
1 24 15 45
2 12 30 27
3 76 20 15
Таким образом, желаемый результат будет
Closest_Value_to_x3
24
30
20
Пожалуйста помоги. Спасибо
Ответы
Ответ 1
Используйте max.col(-abs(data[, 3] - data[, -3]))
чтобы найти положения столбцов ближайших значений, и используйте этот результат как часть матрицы для подмножества ваших данных. Матрица возвращается cbind
.
col <- 3
data[, -col][cbind(1:nrow(data),
max.col(-abs(data[, col] - data[, -col])))]
#[1] 24 30 20
Ответ 2
Вот еще один подход с использованием matrixStats
x <- as.matrix(data[,-3L])
y <- abs(x - .subset2(data, 3L))
x[matrixStats::rowMins(y) == y]
# [1] 24 30 20
Или в base
используя vapply
x <- as.matrix(data[,-3L])
y <- abs(x - .subset2(data, 3L))
vapply(1:nrow(data),
function(k) x[k,][which.min(y[k,])],
numeric(1))
# [1] 24 30 20
Ответ 3
tidyverse
решение:
data %>%
rowid_to_column() %>%
gather(var, val, -c(x3, rowid)) %>%
mutate(temp = x3 - val) %>%
group_by(rowid) %>%
filter(abs(temp) == min(abs(temp))) %>%
ungroup() %>%
select(val)
val
<dbl>
1 24
2 30
3 20
Сначала добавляется идентификатор строки. Во-вторых, он преобразует данные из широких в длинные. В-третьих, он вычисляет разницу между "х3" и другими переменными. Наконец, он группируется по идентификатору строки и сохраняет строки, где абсолютная разница наименьшая.
Или же:
data %>%
rowid_to_column() %>%
gather(var, val, -c(x3, rowid)) %>%
mutate(temp = x3 - val) %>%
group_by(rowid) %>%
filter(abs(temp) == min(abs(temp))) %>%
ungroup() %>%
pull(val)
[1] 24 30 20
Или используя подход, изначально предложенный @markus (предполагается, что ваши столбцы названы "x"):
data %>%
mutate(temp = paste0("x", max.col(-abs(.[, -3] - .[, 3])))) %>%
rowwise() %>%
summarise(val = eval(as.symbol(temp)))
val
<dbl>
1 24.
2 30.
3 20.
Во-первых, он оценивает индекс столбца переменной, где абсолютная разница относительно "x3" является наименьшей и объединяет ее с "x". Затем он оценивает комбинацию x и индекса столбца как переменную и возвращает соответствующее значение.
Также заимствуем идею из @markus (не предполагая, что ваши столбцы названы "x"):
data %>%
mutate(temp = max.col(-abs(.[, -3] - .[, 3]))) %>%
rowwise %>%
mutate(temp = names(.)[[temp]]) %>%
summarise(val = eval(as.symbol(temp)))
Во-первых, это оценка индекса столбца переменной, где абсолютная разница по отношению к "x3" наименьшая. Во-вторых, он возвращает имя столбца на основе индекса столбца. Наконец, он оценивает его как переменную и возвращает соответствующее значение.
Или вариант, в котором вы можете ссылаться на переменную "x3" по ее имени, а не по индексу столбца (основная идея все еще из @markus):
data %>%
mutate(temp = max.col(-abs(.[, !grepl("x3", colnames(.))] - .[, grepl("x3", colnames(.))]))) %>%
rowwise %>%
mutate(temp = names(.)[[temp]]) %>%
summarise(val = eval(as.symbol(temp)))
Ответ 4
Определите функцию closest_to_3
которая работает с вектором и возвращает значение в векторе, которое ближе всего к третьему члену:
closest_to_3 <- function(v) v[-3][which.min(abs( v[-3]-v[3] ))]
(Идиома v[-3]
удаляет третьего члена из v
.) Затем примените эту функцию к каждой строке вашего фрейма данных:
apply(data, 1, closest_to_3)
#[1] 24 30 20