为什么gdata ::: reorder.factor与stats ::: reorder.default的整数和双精度表现不一样?

时间:2013-12-01 21:14:01

标签: r namespaces masking

这是对Reordering factor gives different results, depending on which packages are loaded的跟进,还有另一个相关问题。

@Andrie的答案是正确的,在@David Lovell的评论之后,我因此而成为第三个迷茫的灵魂。

在我的情况下,这是因为我加载了ROCR,这取决于gplots,这取决于gdata,我甚至没有听说过gdata,说明我的无知,因此没有考虑去寻找它。

我发现了另一个怪癖,这让我的情况变得更加困难,这就是这个问题的重点。关于gdata:::reorder.factor的东西以不同的方式处理整数和数字。举例说明:

library(gdata)
x <- factor(letters[1:6])
y <- c(1,4,3,5,6,2)
z <- c(1.1,2.4,1.3,2.5,2.6,1.2)
stats:::reorder.default(x, y, function(X)-X) #edbcfa - correct
stats:::reorder.default(x, z, function(X)-X) #edbcfa
stats:::reorder.default(x, -y)               #edbcfa
stats:::reorder.default(x, -z)               #edbcfa
gdata:::reorder.factor(x, y, function(X)-X)  #edbcfa
gdata:::reorder.factor(x, z, function(X)-X)  #bdeafc - weird
gdata:::reorder.factor(x, -y)                #abcdef - no reordering
gdata:::reorder.factor(x, -z)                #abcdef - no reordering

我感兴趣的主要是 bdeafc 。它在十进制正确之前得到了一点,因为2.x在1.x之前,但在十进制之后的部分point是正常顺序,而不是逆序:x.1之前x.2之前的x.1。

为什么会这样?

1 个答案:

答案 0 :(得分:1)

为什么会这样:

嗯,这似乎是因为gdata:::reorder.factor接受了一个名为sort的参数,默认情况下它的值为mixedsort。此mixedsort参数使用包mixedorder中的gtools函数。通过加载gtools并执行?mixedorder,您可以了解发生这种情况的原因:

  

?mixedorder

     

对嵌入数字的字符串进行排序或排序,以便数字的顺序正确

     

这些函数对包含数字的字符串进行排序或排序,以便对数字进行数字排序,而不是按字符值排序。即“Asprin 50mg”将在“Asprin 100mg”之前出现。此外,忽略字符串的情况,以便“a”将出现在“B”和“C”之前。

同样?reorder.factor明确指出:

  

?gdata:::reorder.factor

     

如果提供了排序(默认情况下):通过将提供的函数应用于现有因子级别名称来生成新的因子级别名称。使用sort = mixedsort,对因子级别进行排序,以便根据字符部分上的字符规则(包括忽略大小写)和数字部分的数字规则对组合的数字和字符串进行排序。有关详细信息,请参阅mixedsort。


解决方案:

您必须为sort参数提供NULL值,以便默认情况下不会使用mixedsort

gdata:::reorder.factor(x, z, function(X)-X, sort=NULL)
# [1] a b c d e f
# Levels: e d b c f a

或者,正如@BenBolker在评论中指出的那样,您可以简单地提供“排序”参数sort

gdata:::reorder.factor(x, z, function(X)-X, sort=sort)

在调试时:

对于未来,debugonce是您这类事情的朋友。通过做

debugonce(gdata:::reorder.factor)
gdata:::reorder.factor(x, z, function(X)-X)

(点击进入并检查输出)你会发现问题来自最后几行:

else if (!missing(FUN)) 
    new.order <- names(sort(tapply(X, x, FUN, ...)))

对于您的数据,

> X
# [1] 1.1 2.4 1.3 2.5 2.6 1.2

> x
# [1] a b c d e f
# Levels: a b c d e f

而且,tapply(...)给出了:

> tapply(X, x, FUN, ...)
#    a    b    c    d    e    f 
# -1.1 -2.4 -1.3 -2.5 -2.6 -1.2 

这里,“排序”应该给出:

> base:::sort(tapply(X, x, FUN, ...))
#    e    d    b    c    f    a 
# -2.6 -2.5 -2.4 -1.3 -1.2 -1.1 

但它给出了:

#   b    d    e    a    f    c 
# -2.4 -2.5 -2.6 -1.1 -1.2 -1.3 

这是因为被调用的“排序”不是来自base,可以通过在调试器中输入“sort”来看到:

> sort # from within the function call (using debugonce)
# function (x) 
# x[mixedorder(x)]
# <environment: namespace:gtools>

mixedorder是包gtools中的函数。由于命令获取names并且排序错误,因此正在获取错误的顺序。所以基本上问题是被调用的sortmixedsort而不是base:::sort

通过安装gtools并执行以下操作来验证这一点很容易:

require(gtools)
gtools:::mixedorder(c(-2.4, -2.5, -2.6))
# [1] 1 2 3

order(c(-2.4, -2.5, -2.6))
# [1] 3 2 1

因此,您必须提供sort=NULL以确保不会发生这种情况。