按R中的首字母和数字对多列进行排序

时间:2018-08-07 17:16:45

标签: r dplyr tidyverse

我创建了一个如下所示的数据框:

item  mean
a_b   5
a_c   2
a_a   4
b_d   7
b_f   3
b_e   1

我想对其进行排序,以使其首先按是否以“ a_”或“ b_”开头进行排序,然后再按均值对其进行排序。最终的数据帧应如下所示:

item  mean
a_c   2
a_a   4
a_b   5
b_e   1
b_f   3
b_d   7

请注意,item列的字母排序并不完美。它仅按首字母排序。

我尝试过:

arrange(df, item, mean) 

此问题是,它不仅按“ a_”和“ b_”类别进行排序,而且按整个项目名称进行排序。

我愿意使用过滤器将原始数据帧分离为单独的数据帧,然后在这些较小的子集中对均值进行排序。我不需要所有内容都保留在同一数据框中。但是,我不确定如何使用过滤器仅选择具有以“ a_”或“ b_”开头的项目的行。

3 个答案:

答案 0 :(得分:2)

使用dplyr的另一种方法:

library(dplyr)
arrange(df, sub('_.+$', '', item), mean)

一种替代方法是使用str_extract中的stringr仅提取item中的第一个字母:

library(stringr)
arrange(df, str_extract(item, '^._'), mean)

结果:

  item mean
1  a_c    2
2  a_a    4
3  a_b    5
4  b_e    1
5  b_f    3
6  b_d    7

数据:

df <- structure(list(item = c("a_b", "a_c", "a_a", "b_d", "b_f", "b_e"
), mean = c(5L, 2L, 4L, 7L, 3L, 1L)), .Names = c("item", "mean"
), class = "data.frame", row.names = c(NA, -6L))

注释:

  • sub('_.+$', '', item)通过删除 _item之后的所有内容来创建一个临时变量。 _.+$与文字下划线(_)匹配,然后在字符串(.+)的末尾匹配一个或多个字符($)。

    < / li>
  • str_extract(item, '^._')通过提取任意一个字符(.)并在其开头添加文字下划线(_)来创建临时变量。字符串(^

  • dplyr::arrange的好处是,您可以在函数内创建一个临时排序变量,而不必将其包含在输出中。

答案 1 :(得分:1)

哲学是,如果您想arrange用某种东西(即此处的子字符串),则必须先获得它:

df = read.table(text = "
item  mean
a_b   5
a_c   2
a_a   4
b_d   7
b_f   3
b_e   1
", header=T, stringsAsFactors=F)

library(tidyverse)

df %>%
  separate(item, c("item1","item2"), remove = F) %>% # split items while keeping the original column
  arrange(item1, mean) %>%                           # arrange by what you really want
  select(item, mean)                                 # keep only relevant columns

#   item mean
# 1  a_c    2
# 2  a_a    4
# 3  a_b    5
# 4  b_e    1
# 5  b_f    3
# 6  b_d    7

请注意,可以使用多种方法从字符串中选择第一个字母。我只是决定在这里使用separate

如果许多项目之间用_分隔,则仍然需要提取第一个项目,因此可以用另一个定界符替换第一个_(假设:)并在此分开您的专栏:

df = read.table(text = "
item  mean
a_b_m   5
a_c   2
a_a   4
b_d_x_q   7
b_f   3
b_e   1
", header=T, stringsAsFactors=F)

library(tidyverse)
library(stringr)

df %>%
  mutate(item2 = str_replace(item, "_", ":")) %>%
  separate(item2, c("item1","item2"), remove = F, sep = ":") %>% 
  arrange(item1, mean) %>%                           
  select(item, mean) 

#      item mean
# 1     a_c    2
# 2     a_a    4
# 3   a_b_m    5
# 4     b_e    1
# 5     b_f    3
# 6 b_d_x_q    7

答案 2 :(得分:0)

一个基本的R解决方案应该是

inx <- order(substr(df$item, 1, 1), df$mean)
newdf <- df[inx, ]

newdf
#  item mean
#2  a_c    2
#3  a_a    4
#1  a_b    5
#6  b_e    1
#5  b_f    3
#4  b_d    7