我有一个具有不同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的值,这将工作正常,但事实并非如此。
如何更改最近的&#34; =#34; 0.5,或者我可以使用另一种功能吗?
提前谢谢!
答案 0 :(得分:7)
您需要计算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
,但您当然可以使用dplyr
或plyr::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)
作为您要最小化的变量。