是否有按字符或间隔因子排序的R函数?

时间:2019-05-29 13:38:26

标签: r dplyr

经过几个函数,我得到了一个表,该表已对字符进行排序,其中一些以“(”或“ [”开头,后跟数字(间隔,来自数据的cut(x))

我要实现的是一个由invervals的起始值决定的顺序,因此(100,124]不比(70,100]早(请参见示例) 编辑:column1(类)的顺序应保持不变。

好吧,我尝试使用data.table中的order和setorder来做到这一点,但到目前为止失败了。我想我需要先用strsplit拆分该列,然后按其第一个元素进行排序,但这不能成为“最佳”解决方案

test <- data.frame(class = c("class1",   "class1",   "class1",   "class1",   "class2", "class2", "class2", "class2", "class2", "class2", "class2", "class2", "class2"),
                   attr = c("1","2","4","5","(100,124]", "(124,180]" ,"(180,Inf]", "(37,50]" ,  "(5,37]"  ,  "(50,56]"  , "(56,70]"  ,"(70,100]"  ,"[0,5]" ),
                  value = c(415.14,115.13,422.52,37.07,167.40,135.04,67.01,280.03,81.18,237.83,285.62,302.63,3.37))

目标:

class   attr    value
class1  1   415.14
class1  2   115.13
class1  4   422.52
class1  5   37.07
class2  [0,5]   3.37
class2  (5,37]  81.18
class2  (37,50] 280.03
class2  (50,56] 237.83
class2  (56,70] 285.62
class2  (70,100]    302.63
class2  (100,124]   167.40
class2  (124,180]   135.04
class2  (180,Inf]   67.01

3 个答案:

答案 0 :(得分:2)

1)base R 用空字符串替换逗号及其后的所有内容以及所有非数字。将其转换为数字并计算将其排序的索引o。最后用test下标o

o <- with(test, order(class, as.numeric(gsub(",.*|\\D", "", attr))))
test[o, ]

给予:

    class      attr     value
1  class1         1  977.0947
2  class1         2  299.9418
3  class1         4 1398.7519
4  class1         5  170.8434
13 class2     [0,5]  299.1390
9  class2    (5,37]  326.5092
8  class2   (37,50]  923.6778
10 class2   (50,56]  734.9950
11 class2   (56,70]  820.7536
12 class2  (70,100]  779.0926
5  class2 (100,124]  308.5136
6  class2 (124,180]  234.6386
7  class2 (180,Inf]  100.1264

1a)也适用。它匹配一个可选的初始非数字,后跟数字,然后再加上其他任何东西,并全部替换为数字。然后按上述步骤进行。

o <- with(test, order(class, as.numeric(gsub("^\\D?(\\d+).*", "\\1", attr))))
test[o, ]

2)dplyr

也可以使用dplyr arrange来完成上述操作:

library(dplyr) 

test %>% arrange(class, attr %>% gsub(",.*|\\D", "", .) %>% as.numeric)

2a)的一种变化是删除(/ [和逗号等部分在单独的子语句中:

test %>% 
  arrange(class, attr %>% 
                   sub("^\\D", "", .) %>%
                   sub(",.*", "", .) %>%
                    as.numeric)

答案 1 :(得分:2)

带有tidyverse

的选项
library(tidyverse)
test %>% 
   arrange(class, as.numeric(str_extract(attr, "\\d+")))
#  class      attr  value
#1  class1         1 415.14
#2  class1         2 115.13
#3  class1         4 422.52
#4  class1         5  37.07
#5  class2     [0,5]   3.37
#6  class2    (5,37]  81.18
#7  class2   (37,50] 280.03
#8  class2   (50,56] 237.83
#9  class2   (56,70] 285.62
#10 class2  (70,100] 302.63
#11 class2 (100,124] 167.40
#12 class2 (124,180] 135.04
#13 class2 (180,Inf]  67.01

注意:没有结实的种子

答案 2 :(得分:0)

stringi备选方案,使用与@G相同的逻辑。格洛腾迪克的解决方案。它提取attr列中的第一个数字序列:

o2 <- order(test$class, as.numeric(stringi::stri_extract_first_regex(test$attr, "\\d+")))
test[o2, ]

    class      attr     value
1  class1         1  977.0947
2  class1         2  299.9418
3  class1         4 1398.7519
4  class1         5  170.8434
13 class2     [0,5]  299.1390
9  class2    (5,37]  326.5092
8  class2   (37,50]  923.6778
10 class2   (50,56]  734.9950
11 class2   (56,70]  820.7536
12 class2  (70,100]  779.0926
5  class2 (100,124]  308.5136
6  class2 (124,180]  234.6386
7  class2 (180,Inf]  100.1264