получить соответствующее значение одного столбца на основе минимального значения другого в R

#r #dataframe #dplyr

#r #dataframe #dplyr

Вопрос:

У меня есть несколько пар переменных, например, X1 и Y1, X2 и Y2 … Xn и Yn и т.д.). Я знаю, как получить минимальное значение некоторых столбцов, например (X1, X2 … Xn), но я хотел бы найти значение Y, соответствующее минимальному значению X. Я думал о потенциально какой-то паре ключ / значение… помогло бы, но не могу понять, как это реализовать. Если бы кто-нибудь мог помочь с какой-либо формой решения, это было бы фантастически.

 # Make some dummy data
X1 = c(1,20,3,40,5)
Y1 = c(20,32,60,82,100)
X2 = c(10,2,30,4,50)
Y2= c(2,30,6,80,10)
df = data.frame(X1,Y1,X2,Y2)

 # This is what the dataframe looks like 
  X1  Y1 X2 Y2
1  1  20 10  2
2 20  32  2 30
3  3  60 30  6
4 40  82  4 80
5  5 100 50 10

# create column of minimum X values
df$minX = c(pmin( df[,1], df[,3]))
 

Я хочу создать еще один столбец со значением Y, соответствующим минимальному значению X, но не могу понять, как это сделать. В приведенном выше примере результирующий dataframe должен выглядеть примерно следующим образом. ПРИМЕЧАНИЕ: соответствующее значение Y не обязательно является максимальным или минимальным).

   X1  Y1 X2 Y2 minX correspondingY
1  1  20 10  2    1             20
2 20  32  2 30    2             30
3  3  60 30  6    3             60
4 40  82  4 80    4             80
5  5 100 50 10    5            100
 

Любая помощь будет оценена. Заранее спасибо.

Ответ №1:

Возможно, вы можете попробовать приведенный ниже код

 X <- df[startsWith(names(df), "X")]
df$minX <- do.call(pmin, X)
df$correspondingY <- df[startsWith(names(df), "Y")][cbind(seq(nrow(X)), max.col(-X))]
 

что дает

 > df
  X1  Y1 X2 Y2 minX correspondingY
1  1  20 10  2    1             20
2 20  32  2 30    2             30
3  3  60 30  6    3             60
4 40  82  4 80    4             80
5  5 100 50 10    5            100
 

Ответ №2:

В tidyverse вы можете сделать :

 library(dplyr)

df1 <- df %>% mutate(row = row_number()) 

df1 %>%
  inner_join(
df1 %>%
  tidyr::pivot_longer(cols = -row,
               names_to = c('.value'), 
               names_pattern = '([A-Z])') %>%
  group_by(row) %>%
  slice(which.min(X)),  by = 'row')

#  X1  Y1 X2 Y2 row X   Y
#1  1  20 10  2   1 1  20
#2 20  32  2 30   2 2  30
#3  3  60 30  6   3 3  60
#4 40  82  4 80   4 4  80
#5  5 100 50 10   5 5 100
 

Вы можете удалить row столбец, если он не нужен.