我最近从JBGruber获得了this amazing answer,用于排序具有双数值的字符串列,这适用于本文底部的两个数据集:

library(magrittr)
order_cols <- function(dat) {
  
  # look for words to order by
  s_ordered <- stringi::stri_extract_all_regex(colnames(dat), "[[:alpha:]]+") %>% 
    unlist() %>% 
    unique() %>% 
    sort()
  
  if (length(s_ordered) > 1) {
    # replace words with their alphabetical index
    cnames <- stringi::stri_replace_all_fixed(colnames(dat), s_ordered, seq_along(s_ordered), vectorise_all = FALSE)
  } else {
    cnames <- colnames(dat)
  }
  
  cnames %>% 
    stringi::stri_extract_all_regex("\\d+") %>% # extract all numbers (including the alphabetical index numbers)
    lapply(as.numeric) %>% 
    lapply(sum) %>% 
    unlist() %>% 
    order()
  
}

然而,我注意到,对于以下数据,它并不完全有效,因为它基于这样一个假设,即按顺序排列的数字之和给出了列的写入顺序:

dat_I <- structure(list(`[25,250)`=3L, `[0,25)` = 5L, `[100,250)` = 43L, `[100,500)` = 0L, 
    `[1000,1000000]` = 20L, `[1000,1500)` = 0L, `[1500,3000)` = 0L, 
    `[25,100)` = 38L, `[25,50)` = 0L, `[250,500)` = 27L, `[3000,1000000]` = 0L, 
    `[50,100)` = 0L, `[500,1000)` = 44L, `[500,1000000]` = 0L), row.names = "Type_A", class = "data.frame")

colnames(dat_I )[order_cols(dat_I)]

有没有办法先按第一个元素排序,然后按第二个元素排序?

Old Data

dat_I <- structure(list(`[0,25)` = 5L, `[100,250)` = 43L, `[100,500)` = 0L, 
    `[1000,1000000]` = 20L, `[1000,1500)` = 0L, `[1500,3000)` = 0L, 
    `[25,100)` = 38L, `[25,50)` = 0L, `[250,500)` = 27L, `[3000,1000000]` = 0L, 
    `[50,100)` = 0L, `[500,1000)` = 44L, `[500,1000000]` = 0L), row.names = "Type_A", class = "data.frame")

dat_II <- structure(list(`[0,25) east` = c(1269L, 85L), `[0,25) north` = c(364L, 
21L), `[0,25) south` = c(1172L, 97L), `[0,25) west` = c(549L, 
49L), `[100,250) east` = c(441L, 149L), `[100,250) north` = c(224L, 
45L), `[100,250) south` = c(521L, 247L), `[100,250) west` = c(770L, 
124L), `[100,500) east` = c(0L, 0L), `[100,500) north` = c(0L, 
0L), `[100,500) south` = c(0L, 0L), `[100,500) west` = c(0L, 
0L), `[1000,1000000] east` = c(53L, 0L), `[1000,1000000] north` = c(82L, 
0L), `[1000,1000000] south` = c(23L, 0L), `[1000,1000000] west` = c(63L, 
0L), `[1000,1500) east` = c(0L, 0L), `[1000,1500) north` = c(0L, 
0L), `[1000,1500) south` = c(0L, 0L), `[1000,1500) west` = c(0L, 
0L), `[1500,3000) east` = c(0L, 0L), `[1500,3000) north` = c(0L, 
0L), `[1500,3000) south` = c(0L, 0L), `[1500,3000) west` = c(0L, 
0L), `[25,100) east` = c(579L, 220L), `[25,100) north` = c(406L, 
58L), `[25,100) south` = c(1048L, 316L), `[25,100) west` = c(764L, 
131L), `[25,50) east` = c(0L, 0L), `[25,50) north` = c(0L, 0L
), `[25,50) south` = c(0L, 0L), `[25,50) west` = c(0L, 0L), `[250,500) east` = c(232L, 
172L), `[250,500) north` = c(207L, 40L), `[250,500) south` = c(202L, 
148L), `[250,500) west` = c(457L, 153L), `[3000,1000000] east` = c(0L, 
0L), `[3000,1000000] north` = c(0L, 0L), `[3000,1000000] south` = c(0L, 
0L), `[3000,1000000] west` = c(0L, 0L), `[50,100) east` = c(0L, 
0L), `[50,100) north` = c(0L, 0L), `[50,100) south` = c(0L, 0L
), `[50,100) west` = c(0L, 0L), `[500,1000) east` = c(103L, 0L
), `[500,1000) north` = c(185L, 0L), `[500,1000) south` = c(66L, 
0L), `[500,1000) west` = c(200L, 0L), `[500,1000000] east` = c(0L, 
288L), `[500,1000000] north` = c(0L, 120L), `[500,1000000] south` = c(0L, 
229L), `[500,1000000] west` = c(0L, 175L)), row.names = c("A", 
"B"), class = "data.frame")

推荐答案

我修改了函数的最后三行,以便顺序现在依次基于每个元素.

order_cols <- function(dat) {
  
  # look for words to order by
  s_ordered <- stringi::stri_extract_all_regex(colnames(dat), "[[:alpha:]]+") %>% 
    unlist() %>% 
    unique() %>% 
    sort()
  
  if (length(s_ordered) > 1) {
    # replace words with their alphabetical index
    cnames <- stringi::stri_replace_all_fixed(colnames(dat), s_ordered, seq_along(s_ordered), vectorise_all = FALSE)
  } else {
    cnames <- colnames(dat)
  }
  
  cnames %>% 
    stringi::stri_extract_all_regex("\\d+") %>% # extract all numbers (including the alphabetical index numbers)
    lapply(as.numeric) %>% 
    do.call(rbind, .) %>%    # bind list items to a matrix
    as.data.frame %>%        # change the matrix to a data.frame (i.e. a list)
    do.call(order, .)        # use the list for ordering
}
colnames(dat_II)[order_cols(dat_II)]
# [1] "[0,25) east"          "[0,25) north"         "[0,25) south"        
# [4] "[0,25) west"          "[25,50) east"         "[25,50) north"       
# [7] "[25,50) south"        "[25,50) west"         "[25,100) east"       
# [10] "[25,100) north"       "[25,100) south"       "[25,100) west"       
# [13] "[50,100) east"        "[50,100) north"       "[50,100) south"      
# [16] "[50,100) west"        "[100,250) east"       "[100,250) north"     
# [19] "[100,250) south"      "[100,250) west"       "[100,500) east"      
# [22] "[100,500) north"      "[100,500) south"      "[100,500) west"      
# [25] "[250,500) east"       "[250,500) north"      "[250,500) south"     
# [28] "[250,500) west"       "[500,1000) east"      "[500,1000) north"    
# [31] "[500,1000) south"     "[500,1000) west"      "[500,1000000] east"  
# [34] "[500,1000000] north"  "[500,1000000] south"  "[500,1000000] west"  
# [37] "[1000,1500) east"     "[1000,1500) north"    "[1000,1500) south"   
# [40] "[1000,1500) west"     "[1000,1000000] east"  "[1000,1000000] north"
# [43] "[1000,1000000] south" "[1000,1000000] west"  "[1500,3000) east"    
# [46] "[1500,3000) north"    "[1500,3000) south"    "[1500,3000) west"    
# [49] "[3000,1000000] east"  "[3000,1000000] north" "[3000,1000000] south"
# [52] "[3000,1000000] west

R相关问答推荐

将第二个图放置在ggplot 2中另一个图的x轴上

在之前合并的数据.tables中分配新列后.internal.selfref无效

按条件计算观察次数

为什么stat_bin在R中的ggplot中显示错误的数字?

在ComplexHeatmap中,如何更改anno_barplot()标题的Angular ?

隐藏e_mark_line的工具提示

如何删除gggvenn与gggplot绘制的空白?

如何写一个R函数来旋转最后n分钟?

如何在编辑列时更新可编辑数据表,并使用该表在Shiny中执行连续计算

在ggplot2中更改小提琴情节的顺序

如何从R ggplot图片中获取SVG字符串?

以更少间隔的较小表中的聚合离散频率表

通过在colname中查找其相应值来创建列

给定开始日期和月份(数字),如何根据R中的开始日期和月数创建日期列

在R函数中使用加号

当我添加美学时,geom_point未对齐

在另一个包中设置断点&S R函数

停止ggplot将多行减少到一行

在使用SliderInput In Shiny(R)设置输入数据的子集时,保留一些情节痕迹

排序R矩阵的行和列