我需要创建一个变量,该变量在数据集中的某些特定列中选择与另一特定列最接近的一个

时间:2019-07-01 02:24:51

标签: r dplyr

我有一个与此类似的数据集:

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))

我需要创建一列,为每一行产生最接近x列的var1,var2和var3列中的值,而忽略var1:var3中的NA。

类似的东西:

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列的值,那就更好了。

我在这篇文章中发现了一些非常接近我需要的东西: Closest value to a specific column in R

但是,由于这个事实,我有更多的列,并且我只想选择以特定单词开头的列,所以我不知道该如何应用类似的问题。

编辑:我需要将变量中的NA与“ x”进行比较以被忽略。

2 个答案:

答案 0 :(得分:4)

这是使用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)))]

答案 1 :(得分:0)

“整洁”的方法

更“整洁”的解决方案可能是这些方面的事情。

data %>%

    # reshape data to long format w/ row numbers
    mutate(row = row_number()) %>%
    gather(col, val, starts_with('var')) %>%

    # compute the minimum difference row-by-row
    group_by(row) %>%
    summarize(closest_to_x = val[which.min(abs(val - x))]) %>%

    # the next two lines just take the new column and paste it back onto the original data
    select(closest_to_x) %>%
    bind_cols(data, .)

这有点冗长,但是我觉得它相当可读(当然是YMMV)。不确定性能。它不使用max.col()pmin(),而是依靠将数据重新格式化为“整齐”的格式,其中您关心的所有列的值都放在单个{{1}中}列。