Ближайшее значение к конкретному столбцу в R - PullRequest
0 голосов
/ 23 января 2019

Я хотел бы найти ближайшее значение для столбца х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

Пожалуйста, помогите. Спасибо

Ответы [ 4 ]

0 голосов
/ 23 января 2019

Определите функцию 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
0 голосов
/ 23 января 2019

Вот еще один подход, использующий 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
0 голосов
/ 23 января 2019

A 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)))
0 голосов
/ 23 января 2019

Используйте 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
...