使用gtools :: mixedsort或替代dplyr :: arrange

时间:2015-09-03 14:14:46

标签: r dplyr

我正在尝试使用dplyr::arrange订购数据框。问题是我尝试排序的列包含一个固定字符串后跟一个数字,例如由下面的虚拟代码生成。

  dummydf<-data.frame(values=rnorm(100),sortcol=paste0("ABC",sample(1:100,100,replace=FALSE)))

默认情况下,使用dummydf %>% arrange(sortcol)会生成一个按字母数字(?)排序的df,但这当然不是理想的结果:

values sortcol
0.708081720    ABC1
0.041348322   ABC10
1.730962886  ABC100
0.423480861   ABC11
-1.545837266   ABC12
-1.345539947   ABC13
-0.078998792   ABC14
0.088712174   ABC15
0.670583024   ABC16
1.238837680   ABC17
-1.459044293   ABC18
-2.028535223   ABC19
0.779514385    ABC2
1.360509910   ABC20

在这个例子中,我想按gtools::mixedsort的方式对列进行排序,确保ABC2跟在ABC1之后,并且不在ABC1-19之前,而ABC100 mixedsort(as.character(dummydf$sortcol))也会这样做。

现在,我知道我可以在我的sub参数arrange中使用dummydf %>% arrange(as.numeric(sub("ABC","",sortcol)))来做到这一点,但这主要是因为我的字符串是固定的(尽管可以使用任何正则表达式)捕获任何字符串后面的最后数字我想。

我只是想知道:是否有更“优雅”和通用的方法来完成dplyr::arrange,与gtools::mixedsort一样?

亲切的问候,

FM

4 个答案:

答案 0 :(得分:4)

这是一个利用mysterious身份order(order(x)) == rank(x)的功能解决方案。

mixedrank = function(x) order(gtools::mixedorder(x))
dummydf %>% dplyr::arrange(mixedrank(sortcol))

答案 1 :(得分:2)

使用data.table

library(data.table)
dummydf = data.table(dummydf)
dummydf[gtools::mixedorder(as.character(sortcol))]

老实说,只是复制了你的例子并将其作为data.table语法中的select参数插入。你已经完成了所有艰苦的工作:)。

答案 2 :(得分:1)

我没有看到这个答案发布,所以我会把它扔掉。您可以使用带有切片的混合顺序来排列它。

dummydf %>% 
  slice(mixedorder(sortcol))

答案 3 :(得分:0)

感谢Akhil Nair的data.table答案,这是第一个代码段的来源。如果您喜欢data.table的答案,但仍希望使用magrittr管道,则可以考虑计算新列,并将管道与data.table一起使用以获取输出:

dummydf %>% 
  dplyr::mutate(row_lookup = gtools::mixedorder(as.character(sortcol))) %>%
  data.table::data.table() %>% 
  .[.$row_lookup]

我认为这是否有助于或损害可读性尚待商

如果您不想调用data.table,则可以进行一些额外的计算来计算可以使用dplyr::arrange的列。这是一个示例:

library(dplyr)
bind_cols(dummydf,
          dummydf %>% 
            tibble::rowid_to_column("order") %>% 
            mutate(rowname = gtools::mixedorder(as.character(sortcol))) %>% 
            arrange(rowname) %>% 
            select(order)) %>% 
arrange(order)

我认为这段代码更容易阅读,不值得为了避免data.table而过度扭曲。