我有一个与此类似的数据集:
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”进行比较以被忽略。
答案 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}中}列。