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

这是我的数据框:
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 YDB1 0.10 0.49DB2 0.10 0.51DB3 0.30 0.49DB4 0.20 0.50
我知道我可以使用这样的东西用ddply添加一个过滤器
ddply(df, .(ID), function(z) { z[z$Y == 0.50, ][1, ]})并且如果Y中的值始终为0.50,则效果会很好,事实并非如此。

如何将“最近”的==更改为0.5,或者我可以使用另一个函数代替?

先感谢您!

最佳答案

您需要从0.5计算出差异,然后保持最小的差异。一种方法是这样的:

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

注意,上面我编码的方式,省略了[1, ],如果两行被精确地捆绑在一起,则将两者都保留。

没关系,因为我们在==的每一侧都进行了完全相同的计算,但是我经常担心数值精度问题,因此我们可以改用which.min。请注意,如果出现平局,which.min将返回第一个最小值。
ddply(df, .(ID), function(z) {
  z[which.min(abs(z$Y - 0.50)), ]
})

另一种可靠的方法是按0.5的差异对数据帧进行排序,并保持每个ID的第一行。在这一点上,我将过渡到dplyr,尽管您当然可以为这些方法中的任何一种使用dplyrplyr::ddply
library(dplyr)
df %>% group_by(ID) %>%
  arrange(abs(Y - 0.5)) %>%
  slice(1)

我不确定arrange如何处理关系。有关更多方法,请参见Get rows with minimum of variable, but only first row if multiple minima,并且始终将abs(Y - 0.5)用作要最小化的变量。

关于返回在R中建立 "closest value to"的行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41496276/

10-12 20:32