【问题标题】:Return value based on finding closest value between other two columns in df基于在 df 中找到其他两列之间最接近的值的返回值
【发布时间】:2017-09-22 15:11:12
【问题描述】:

我的问题几乎与this one 相同,只是不是在列值和固定数字之间找到最接近的值,例如“2”,我想找到与另一列中的值最接近的值。。 这是一个数据示例:

    df <- data.frame(site_no=c("01010500", "01010500", "01010500","02010500", "02010500", "02010500", "03010500", "03010500", "03010500"), 
                     OBS=c(423.9969, 423.9969, 423.9969, 123, 123, 123, 150,150,150),
                     MOD=c(380,400,360,150,155,135,170,180,140),
                     HT=c(14,12,15,3,8,19,12,23,10))

看起来像这样:

   site_no      OBS MOD HT
1 01010500 423.9969 380 14
2 01010500 423.9969 400 12
3 01010500 423.9969 360 15
4 02010500 123.0000 150  3
5 02010500 123.0000 155  8
6 02010500 123.0000 135 19
7 03010500 150.0000 170 12
8 03010500 150.0000 180 23
9 03010500 150.0000 140 10

目标是,对于每一个“site_no”,找到与OBS值最接近的MOD值,然后返回对应的HT。例如,对于 site_no 01010500,423.9969 - 400 产生最小差异,因此该函数将返回 12。我已经尝试了另一篇文章中的大多数解决方案,但由于 $ 与原子向量(df 是递归的)而出现错误,但我认为功能不是)。我试过了:

ddply(df, .(site_no), function(z) {
  z[abs(z$OBS - z$MOD) == min(abs(z$OBS - z$MOD)), ]
}) 
Error in z$River_Width..m. - z$chan_width :
  non-numeric argument to binary operator

【问题讨论】:

  • 可能是library(dplyr); df %&gt;% group_by(site_no) %&gt;% slice(which.min(HT)),也可能是df %&gt;% group_by(site_no) %&gt;% slice(which.min(abs(OBS-MOD)))
  • @akrun,第二个选项效果很好。如果您作为一个提交,我可以接受它作为答案。唯一的问题:返回的 str 是一个 tibble,以及一些数据帧的组合 tbl。我可以在单个数据帧中得到这个结果吗?
  • 谢谢。我将我的评论作为解决方案添加了一些解释。如果需要,您可以转换为 data.frame

标签: r dataframe match plyr


【解决方案1】:

在按'site_no'分组后,我们slice'OBS'和'MOD'之间绝对差值最小的行

library(dplyr)
res <- df %>%
         group_by(site_no) %>% 
         slice(which.min(abs(OBS-MOD)))

注意:通过使用dplyr,添加了一些额外的类,如tbl_df tibble 等,它们应该与大多数其他功能一起使用。如果有任何问题,我们可以将其转换为data.frame as.data.frame

str(res %>%
        as.data.frame)
#'data.frame':   3 obs. of  4 variables:
#$ site_no: Factor w/ 3 levels "01010500","02010500",..: 1 2 3
#$ OBS    : num  424 123 150
#$ MOD    : num  400 135 140
#$ HT     : num  12 19 10

【讨论】:

  • 我对此有一点小问题。如果出现平局,操作员会返回索引中的第一个值。理想情况下,我希望它返回最大(HT)。无法使用 slice 来解决这个问题。尝试移动到过滤和排名,但没有这样的运气。
  • @LauraR 在这种情况下,df %&gt;% group_by(site_no) %&gt;% arrange(site_no, desc(HT)) %&gt;% slice(which.min(abs(OBS-MOD)))你可以在更改df$MOD[5] &lt;- 135后检查一下
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-13
  • 1970-01-01
相关资源
最近更新 更多