Мне нужно создать переменную, которая выбирает, среди некоторых определенных столбцов в наборе данных, тот, который ближе всего к другому конкретному столбцу - PullRequest
1 голос
/ 01 июля 2019

У меня есть набор данных, похожий на этот:

data= data.frame(a=c(33,44,55), b= c(99,77,NA,66), 
      var1=c(1,2,3,NA),var2=c(5,6,NA,7),var3=c(8,9,10,NA), x = c(6,5,4,3))

Мне нужно создать столбец, который возвращает для каждой строки значение среди столбцов var1, var2 и var3, которое ближе всего к столбцу x, игнорируя NA в var1: var3.

Что-то вроде:

closest_x
  5
  6
  3
  7

В моей реальной задаче у меня намного больше столбцов, чем это, поэтому я хотел бы использовать starts_with, чтобы выбрать столбцы для сравнения с X(столбцы представлены как «var1» и т. д. выше).

Я попытался создать столбцы с модульной разницей между столбцом X и столбцами "var", затем я попробовал что-то вроде:

data %>% mutate(pmin = pmin(starts_with("var")))

или

mutate(data, C = pmin(starts_with("var")))

, а также

data %>% with(pmin(starts_with("var")))

Это говорит о том, что контекст переменной не установлен.Кроме того, было бы лучше, если бы мне не нужно было создавать много других переменных с этим модульным различием и перейти к ближайшему значению к столбцу X.

Я нашел очень близкие к тому, что янужно в этом посте: Ближайшее значение к конкретному столбцу в R

Однако я не знаю, как применить что-то похожее на мою проблему из-за того факта, что у меня есть еще много столбцови я хочу выбрать только те, которые начинаются с определенного слова.

РЕДАКТИРОВАТЬ: мне нужно, чтобы NA в переменных сравнивались с "х", чтобы игнорировать.

Ответы [ 2 ]

4 голосов
/ 01 июля 2019

Вот один векторизованный способ, используя max.col

cols <- grep("^var", names(data))
data$closest_x <- data[cols][cbind(1:nrow(data), 
                      max.col(-abs(data[cols] - data$x)))]

#   a  b var1 var2 var3  x closest_x
#1 33 99   24   15   45 11        15
#2 44 77   12   30   27 22        27
#3 55 66   76   20   15 33        20

Или используя apply

data$closest_x <- apply(data, 1, function(p) 
                  p[cols][which.min(abs(p[cols] - p["x"]))])

Если в данных есть значения NA, мы можемзамените их -Inf, а затем подмножество

temp_df <- -abs(data[cols] - data$x)
data$closest_x <- data[cols][cbind(1:nrow(data), 
                   max.col(replace(temp_df, is.na(temp_df), -Inf)))]
0 голосов
/ 02 июля 2019

«аккуратный» подход

Более «аккуратное» решение может быть чем-то вроде этогоконечно).Не уверен насчет производительности.Он не использует max.col() или pmin(), но полагается на переформатирование данных в «аккуратный» формат, где значения всех интересующих вас столбцов помещаются в один столбец val.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...