计算三列之间的最小差异,并在R中给出相应的列名称

时间:2016-06-13 23:50:11

标签: r dplyr

假设我有如下数据,

data

required_value          Value1          Value2        Value3
     0.5                  .1              0.3           0.4
     1.0                   1              0.7           0.2
     1.5                  .37             0.3           0.7
     2.0                  1.25            0.9           1.9

我想找到三列中的哪一列(Value1,Value2,Value3)最接近所需的值并创建一个新列并具有该列的列名。我的示例输出是,

数据

required_value          Value1          Value2        Value3       output
     0.5                  .1              0.3           0.4        Value3
     1.0                   1              0.7           0.2        Value1
     1.5                  .37             0.3           0.7        Value3
     2.0                  1.25            0.9           1.9        Value3

我能够在此找到壁橱值。但是无法获得相应的列名。有人可以帮我这么做吗?

由于

3 个答案:

答案 0 :(得分:3)

根据我更好的判断,将这个回答看作是家庭作业。

read.table(text="required_value          Value1          Value2        Value3
     0.5                  .1              0.3           0.4
     1.0                   1              0.7           0.2
     1.5                  .37             0.3           0.7
     2.0                  1.25            0.9           1.9", header=TRUE) -> df


df$output <- apply(df, 1, function(x) {
  names(x)[which.min(abs(x[2:4] - x[1]))+1]
})

##   required_value Value1 Value2 Value3 output
## 1            0.5   0.10    0.3    0.4 Value3
## 2            1.0   1.00    0.7    0.2 Value1
## 3            1.5   0.37    0.3    0.7 Value3
## 4            2.0   1.25    0.9    1.9 Value3

更新:

我知道sweep()中有很多代码,但是,哇:

Unit: microseconds
  expr      min       lq     mean   median       uq      max neval
 apply   83.281  103.156  117.414  113.479  126.790  256.216   100
 sweep 1116.052 1194.766 1292.346 1218.801 1301.724 2309.745   100

enter image description here

答案 1 :(得分:3)

在清除第一列与其余列之间的差异后,您可以将其分解为?max.col操作:

names(df[-1])[max.col(-abs(sweep(df[-1], 1, df$required_value)),"first")]
#[1] "Value3" "Value1" "Value3" "Value3"

要解决@hrbrmstr的基准测试,表明这种情况比较慢。是的,当数据很小时会慢一些,因为函数的开销会花费几微秒。但是,这个代码应该进行缩放,这样当你在小数据上输掉几分之一秒时,它会随着大小的增加而快速运行。 中的示例时间:

-sweep/max.col
           user  system elapsed
10k        0.00    0.00    0.00
100k       0.17    0.01    0.19
1M         1.36    0.12    1.49 
5M         3.99    0.59    4.58 

-apply
           user  system elapsed 
10k        0.05    0.00    0.05
100k       0.56    0.00    0.57
1M         7.33    0.08    7.41
5M        41.36    0.13   41.52 

答案 2 :(得分:1)

您还可以将数据从宽格式转换为长格式,然后过滤掉与所需值具有最小差异的变量:

library(data.table)
data$id <- seq_len(nrow(data))   # create an id variable for group by operation
longData <- melt(data, id.vars = c("id", "required_value"))   # transform to long format
data[longData[, .(variable[which.min(abs(value - required_value))]) ,.(id)], on = "id"]

   required_value Value1 Value2 Value3 id     V1
1:            0.5   0.10    0.3    0.4  1 Value3
2:            1.0   1.00    0.7    0.2  2 Value1
3:            1.5   0.37    0.3    0.7  3 Value3
4:            2.0   1.25    0.9    1.9  4 Value3