假设我有如下数据,
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
我能够在此找到壁橱值。但是无法获得相应的列名。有人可以帮我这么做吗?
由于
答案 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
答案 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