返回在R中建立"最接近的值"的行

mgm*_*392 3 r subset plyr

我有一个具有不同ID的数据框,我想创建一个子组,其中:对于每个ID,我将只获得一行,其中最接近的值为0.5,在变量Y中.

这是我的数据框:

df <- data.frame(ID=c("DB1", "BD1", "DB2", "DB2", "DB3", "DB3", "DB4", "DB4", "DB4"), X=c(0.04, 0.10, 0.10, 0.20, 0.02, 0.30, 0.01, 0.20, 0.30), Y=c(0.34, 0.49, 0.51, 0.53, 0.48, 0.49, 0.49, 0.50, 1.0) )

这就是我想要的

ID X Y DB1 0.10 0.49 DB2 0.10 0.51 DB3 0.30 0.49 DB4 0.20 0.50

我知道我可以使用类似这样的东西添加ddply过滤器

ddply(df, .(ID), function(z) { z[z$Y == 0.50, ][1, ] })
如果在Y中总是有0.50的值,这将工作正常,但事实并非如此.

如何将==更改为"最接近"0.5,或者是否有另一个我可以使用的函数?

先感谢您!

Gre*_*gor 7

您需要计算0.5之差,然后保持最小值.一种方法是这样做:

ddply(df, .(ID), function(z) {
  z[abs(z$Y - 0.50) == min(abs(z$Y - 0.50)), ]
})
Run Code Online (Sandbox Code Playgroud)

请注意我上面编码的方式,省略你的[1, ],如果两行完全绑定,将保留.

它应该没问题,因为我们在两侧进行完全相同的计算==,但我经常担心数值精度问题,所以我们可以改用which.min.请注意,which.min在平局的情况下将返回第一个最小值.

ddply(df, .(ID), function(z) {
  z[which.min(abs(z$Y - 0.50)), ]
})
Run Code Online (Sandbox Code Playgroud)

另一种强有力的方法是按0.5的差异对数据帧进行排序,并保留每个ID的第一行.在这一点上,我将过渡到dplyr,但当然你可以使用dplyrplyr::ddply用于任何这些方法.

library(dplyr)
df %>% group_by(ID) %>%
  arrange(abs(Y - 0.5)) %>%
  slice(1)
Run Code Online (Sandbox Code Playgroud)

我不确定如何arrange处理关系.有关更多方法,请参阅获取具有最小变量的行,但只有第一行(如果有多个最小值),并且始终abs(Y - 0.5)用作最小化的变量.

  • 或者`df %&gt;% group_by(ID) %&gt;% filter(row_number()==which.min(abs(Y-0.5)))` (2认同)
  • @HubertL 那时只是`df %&gt;% group_by(ID) %&gt;% slice(which.min(abs(Y - 0.5)))` (2认同)