【问题标题】:Calculate the minimum difference among the three column and give the corresponding column name in R计算三列之间的最小差异,并在R中给出对应的列名
【发布时间】:2016-06-13 23:50:11
【问题描述】:

假设我有如下数据,

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

我能够在其中找到壁橱的价值。但无法获取对应的列名。有人可以帮我做这件事吗?

谢谢

【问题讨论】:

  • 您是如何找到最接近的值的?那段代码似乎不见了。

标签: r dplyr


【解决方案1】:

根据我的更好判断,将这个答案发布到看起来像是家庭作业的作业。

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

【讨论】:

    【解决方案2】:

    在清除第一列和其余列之间的差异后,您可以将其分解为 ?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 
    

    【讨论】:

    • 哇,我没想到基准测试会有这么大的不同,但确实如此。
    • @hrbrmstr - 尝试使用大于 4 行的内容 - 当数据变大时,max.col/sweep 更快 - 尝试 100K 或 1M 行。 1M 扫描为 1.5 秒,而应用为 7.4 秒。 1000 微秒是 0.001 秒,如果您只有少量数据,可能不值得费心。
    【解决方案3】:

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

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-02
      • 2019-07-23
      • 2015-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多