如何根据值的实际顺序将数字转换为字母?

时间:2019-05-21 19:03:13

标签: r dplyr

我认为这应该是一个非常简单的问题,但是我似乎无法找出答案。本质上,我想为列的值添加前缀,但不使用任何类型的条件语句。这可能吗?

即,我想要的东西产生与

相同的结果
mtcars %>% 
  mutate(new_cyl = str_c(case_when(cyl == 6 ~ letters[1],
                                   cyl == 4 ~ letters[2],
                                   cyl == 8 ~ letters[3]), ") ", cyl))

但不使用case_when或任何其他条件。

我的预期输出将按它们出现的顺序在列的值后附加一些内容(在本例中为字母)。看起来像这样:

enter image description here

3 个答案:

答案 0 :(得分:4)

您可以制作一个小的前缀查询表。这样,您知道您正在正确地将cyl值与其前缀匹配,而不是取决于正确数据的顺序。然后将查找加入您的数据并粘贴。

library(dplyr)

lookup <- data.frame(
  cyl = c(6, 4, 8),
  prefix = letters[1:3]
)

对于要基于cyl列的顺序创建前缀的情况,而不是将cyl值硬编码为它们的前缀,可以更动态地创建查找表,例如:

lookup <- data.frame(
  cyl = unique(mtcars$cyl),
  prefix = letters[seq_along(unique(mtcars$cyl))]
)

# select is just to get extra columns out of the way to show here
mtcars %>%
  select(cyl) %>%
  left_join(lookup, by = "cyl") %>%
  mutate(new_cyl = paste(prefix, cyl, sep = ") ")) %>%
  head()
#>   cyl prefix new_cyl
#> 1   6      a    a) 6
#> 2   6      a    a) 6
#> 3   4      b    b) 4
#> 4   6      a    a) 6
#> 5   8      c    c) 8
#> 6   6      a    a) 6

答案 1 :(得分:2)

如果要将字母分配给所有“ cyl”值:

mtcars %>%
 mutate(new_cyl = paste0(letters[cyl], ") ", cyl))

    mpg cyl  disp  hp drat    wt  qsec vs am gear carb new_cyl
1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4    f) 6
2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4    f) 6
3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1    d) 4
4  21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1    f) 6
5  18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2    h) 8
6  18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1    f) 6
7  14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4    h) 8
8  24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2    d) 4
9  22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2    d) 4
10 19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4    f) 6

要根据“ cyl”值的实际顺序分配字母:

mtcars %>%
 mutate(dup = cumsum(!duplicated(cyl))) %>%
 group_by(cyl) %>%
 mutate(dup = first(dup),
        new_cyl = paste0(letters[dup], ") ", cyl)) %>%
 ungroup() %>%
 select(-dup) 

     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb new_cyl
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>  
 1  21       6 160     110  3.9   2.62  16.5     0     1     4     4 a) 6   
 2  21       6 160     110  3.9   2.88  17.0     0     1     4     4 a) 6   
 3  22.8     4 108      93  3.85  2.32  18.6     1     1     4     1 b) 4   
 4  21.4     6 258     110  3.08  3.22  19.4     1     0     3     1 a) 6   
 5  18.7     8 360     175  3.15  3.44  17.0     0     0     3     2 c) 8   
 6  18.1     6 225     105  2.76  3.46  20.2     1     0     3     1 a) 6   
 7  14.3     8 360     245  3.21  3.57  15.8     0     0     3     4 c) 8   
 8  24.4     4 147.     62  3.69  3.19  20       1     0     4     2 b) 4   
 9  22.8     4 141.     95  3.92  3.15  22.9     1     0     4     2 b) 4   
10  19.2     6 168.    123  3.92  3.44  18.3     1     0     4     4 a) 6

在这里,首先创建一个非重复的“ cyl”值的累积和。第二,按“ cyl”分组。最后,它获取非重复值的累加总和的第一个值,并为其分配一个字母。

答案 2 :(得分:1)

您可以将factor()用作标签:

mtcars %>%
  mutate(
    new_cyl = paste(factor(x, unique(x), letters[seq(unique(x))]), cyl, sep = ') ')
  )

输出(头):

#    mpg cyl disp  hp drat    wt  qsec vs am gear carb new_cyl
# 1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4    a) 6
# 2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4    a) 6
# 3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1    b) 4
# 4 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1    a) 6
# 5 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2    c) 8
# 6 18.1   6  225 105 2.76 3.460 20.22  1  0    3    1    a) 6

概括为一个功能

append_prefix <- function(x, sort = F){
  out <- paste(factor(x, unique(x), letters[seq(unique(x))]), x, sep = ') ')
  if(sort) out <- paste(factor(x, sort(unique(x)), letters[seq(unique(x))]), x, sep = ') ')
  return(out)
}