重新排序因子会根据加载的软件包不同而产生不同的结果。

18

我想创建一个条形图,其中的条形按高度而不是按类别字母顺序排序。当我只加载了ggplot2包时,这个方法运行良好。然而,当我加载了几个额外的包并运行了相同的代码以创建、排序和绘制我的数据框时,条形图又恢复了按字母表顺序排序。

我每次都使用str()检查数据框,结果显示数据框的属性现在已经不同,虽然我每次都运行了同样的代码。

我的代码和输出如下。有人能解释这种不同的行为吗?为什么加载几个明显不相关的包(在我使用的函数中似乎没有一个被新加载的包所覆盖)会改变运行transform()函数的结果呢?

案例1:只加载了ggplot2

library(ggplot2)

group = c("C","F","D","B","A","E")
num = c(12,11,7,7,2,1)
data = data.frame(group,num)
data1 = transform(data, group=reorder(group,-num))

> str(data1)
'data.frame':   6 obs. of  2 variables:
 $ group: Factor w/ 6 levels "C","F","B","D",..: 1 2 4 3 5 6
  ..- attr(*, "scores")= num [1:6(1d)] -2 -7 -12 -7 -1 -11
  .. ..- attr(*, "dimnames")=List of 1
  .. .. ..$ : chr  "A" "B" "C" "D" ...
 $ num  : num  12 11 7 7 2 1

情况二:加载多个其他包后,再次运行相同的代码

library(plyr)
library(xtable)
library(Hmisc)
library(gmodels)
library(reshape2)
library(vcd)
library(lattice)

group = c("C","F","D","B","A","E")
num = c(12,11,7,7,2,1)
data = data.frame(group,num)
data1 = transform(data, group=reorder(group,-num))

> str(data1)
'data.frame':   6 obs. of  2 variables:
 $ group: Factor w/ 6 levels "A","B","C","D",..: 3 6 4 2 1 5
 $ num  : num  12 11 7 7 2 1

更新:SessionInfo()

情况1:在加载ggplot2后运行sessionInfo()

> sessionInfo()
R version 2.15.0 (2012-03-30)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)

locale:
  [1] C/en_US.UTF-8/C/C/C/C

attached base packages:
  [1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
  [1] ggplot2_0.9.1

loaded via a namespace (and not attached):
  [1] MASS_7.3-18        RColorBrewer_1.0-5 colorspace_1.1-1   dichromat_1.2-4    digest_0.5.2       grid_2.15.0       
[7] labeling_0.1       memoise_0.1        munsell_0.3        plyr_1.7.1         proto_0.3-9.2      reshape2_1.2.1    
[13] scales_0.2.1       stringr_0.6        tools_2.15.0

情况二:在加载其他软件包后运行sessionInfo()。

> sessionInfo()
R version 2.15.0 (2012-03-30)
Platform: x86_64-apple-darwin9.8.0/x86_64 (64-bit)

locale:
  [1] C/en_US.UTF-8/C/C/C/C

attached base packages:
  [1] grid      splines   stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
  [1] lattice_0.20-6   vcd_1.2-13       colorspace_1.1-1 MASS_7.3-18      reshape2_1.2.1   gmodels_2.15.2  
[7] Hmisc_3.9-3      survival_2.36-14 xtable_1.7-0     plyr_1.7.1       ggplot2_0.9.1   

loaded via a namespace (and not attached):
  [1] RColorBrewer_1.0-5 cluster_1.14.2     dichromat_1.2-4    digest_0.5.2       gdata_2.8.2        gtools_2.6.2      
[7] labeling_0.1       memoise_0.1        munsell_0.3        proto_0.3-9.2      scales_0.2.1       stringr_0.6       
[13] tools_2.15.0

请提供sessionInfo()的输出?如果有人可以帮忙,他们可能需要匹配您的R和包版本以进行复制。 - joran
我可以在最新的CRAN软件包上(在Ubuntu上)使用R 2.15.0复制这个。 - Justin
1
非常有趣。看起来transform()结果的变化只会在加载gmodels后出现(并且随后取消加载gmodels也无法解决)。我很感兴趣...(顺便说一句,我使用的是运行R-devel的Windows XP系统,所以看起来这不是操作系统或版本特定的问题。) - Josh O'Brien
@joran 我已经将sessionInfo()的输出作为我的问题编辑添加了。 - eipi10
通过在加载和不加载library(proto)的情况下运行str,您可以获得大多数ggplot2对象的类似行为。使用proto可以极大地扩展proto对象的显示。 - Faheem Mitha
我认为这也与问题有些相关:https://dev59.com/w3nZa4cB1Zd3GeqPuciO#20335767。简而言之,`reorder`需要第二个参数为`as.factor(.)`才能正确排序。 - Anton Tarasenko
1个回答

13

发生这种情况是因为:

  1. gmodels 导入了 gdata
  2. gdatareorder.factor 创建了一个新的方法

开始一个干净的会话。然后执行以下操作:

methods("reorder")
[1] reorder.default*    reorder.dendrogram*

现在加载gdata (或者加载gmodels,它有相同的效果):

library(gdata)
methods("reorder")
[1] reorder.default*    reorder.dendrogram* reorder.factor 

注意,由于基础包中不存在reorder.factor,因此没有进行遮蔽(masking)。

重新创建问题,但这次需要显式调用不同的包:

group = c("C","F","D","B","A","E")
num = c(12,11,7,7,2,1)
data = data.frame(group,num)

使用基础R版本(使用reorder.default):

str(transform(data, group=stats:::reorder.default(group,-num)))
'data.frame':   6 obs. of  2 variables:
 $ group: Factor w/ 6 levels "C","F","B","D",..: 1 2 4 3 5 6
  ..- attr(*, "scores")= num [1:6(1d)] -2 -7 -12 -7 -1 -11
  .. ..- attr(*, "dimnames")=List of 1
  .. .. ..$ : chr  "A" "B" "C" "D" ...
 $ num  : num  12 11 7 7 2 1

使用reorder.factorgdata版本:

str(transform(data, group=gdata:::reorder.factor(group,-num)))
'data.frame':   6 obs. of  2 variables:
 $ group: Factor w/ 6 levels "A","B","C","D",..: 3 6 4 2 1 5
 $ num  : num  12 11 7 7 2 1

4
使用gdata::reorder.factor版本并添加FUN=identity参数,可以获取“预期”的排序顺序。具体方法是:data1 = transform(data, group=reorder(group,-num,FUN=identity)) - Brian Diggs
2
只是为了确保我理解这个教训: 当您加载一个包时,即使没有掩盖,如果新包具有针对您的对象特定的方法(在本例中为“reorder.factor”),您可以使用完全相同的代码获得不同的行为,这将“覆盖”否则适用于您的对象的“顶层”方法(在这种情况下,通用的“reorder”)的行为。这正确吗? - eipi10
1
@eipi10 是的,你的例子清楚地说明了这一点。关于术语的吹毛求疵:reorder.factor 被调度而不是 reorder.default(因此在某种程度上覆盖了先前的行为)。这是一个非常有趣的问题。谢谢。 - Andrie
Andrie,感谢您清晰详细的回答。@BrianDiggs 感谢您展示如何恢复所需的行为。 - eipi10
1
非常感谢大家。这个问题让我疯狂了。是否有办法添加一些元数据到这个问题中,使其更容易被发现?至少还有另外一个可怜的灵魂处于困惑状态: - David Lovell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接