如何简化mutate()中的case_when()

时间:2019-11-06 11:38:12

标签: r dplyr

我有一个数据框,我想添加一列。为此,我使用dplyr :: mutate。但是,我要添加的列的值取决于其他列的值。我使用case_when()并解决了问题,但是如果有很多情况,代码不适合编写(下面显示一个示例),所以我想知道是否还有另一个选择(可能是循环)来简化此操作。

以下代码有效:

NewTable <- Table %>% 
  dplyr::mutate(ColumnB = case_when(
               ColumnA=="2000" ~ 0,
               ColumnA=="2001" ~ 4,
               ColumnA=="2002" ~ 8,
               ColumnA=="2003" ~ 12,
               ColumnA=="2004" ~ 16,
               ColumnA=="2005" ~ 20,
               ColumnA=="2006" ~ 24,
               ColumnA=="2007" ~ 28,
               ColumnA=="2008" ~ 32,
               ColumnA=="2009" ~ 36,
               ColumnA=="2010" ~ 40,
               ColumnA=="2011" ~ 44))

我该如何改善?非常感谢。

5 个答案:

答案 0 :(得分:1)

由于您更改了数据,因此您可能需要尝试以下操作:

Table<-data.frame(A = c("2000", "2001", "2002", "2003", "2004"))
Table$B = (as.numeric(as.character(Table$A))-2000)*4 

如果没有这种模式,则可以生成具有匹配的A和B的值的列表,然后将它们合并:

match_list<-data.frame(A = c("2000", "2001", "2002", "2003", "2004"),
                       B = c(0, 4, 8, 16, 20))
merge(Table, match_list, by = "A")  # Table itself does not have B at this stage

这只能保存一些键入内容。

答案 1 :(得分:0)

这就是我要做的:

lkp <- setNames(c(0, 4, 8, 16, 20),
                c("2000", "2001", "2002", "2003", "2004"))
df <- data.frame(ColumnA = c("2004","2002"),stringsAsFactors = FALSE)
dplyr::mutate(df, ColumnB = lkp[ColumnA])
#>   ColumnA ColumnB
#> 1    2004      20
#> 2    2002       8

reprex package(v0.3.0)于2019-11-06创建

答案 2 :(得分:0)

由于您正在编写B列,因此我认为Table中不存在该列,因此联接可以解决问题。

library(dplyr)
NewTable <- left_join( Table,
tibble( A = c("2000", "2001", "2002", "2003", "2004"),
        B = seq(from = 0, to = 32, by = 4) )

答案 3 :(得分:0)

这是一个使用mapvalues软件包中的plyr的解决方案。我经常使用。

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
# Create a simulated data frame

set.seed(9049)

Table <- data.frame(columnA = as.character(sample(2000:2011, 
                                                  size = 100, 
                                                  replace = TRUE)),
                    stringsAsFactors = FALSE)

# Extract unique levels from column A
colA_levels <- unique(Table$columnA)

# Create unique levels of column B to map to
colB_levels <- (as.numeric(colA_levels) - 2000) * 4

# Use `mapvalues` from `plyr` package
# 
NewTable <- Table %>% 
  mutate(columnB = plyr::mapvalues(columnA,
                                   from = colA_levels,
                                   to = colB_levels))

head(NewTable, 10)
#>    columnA columnB
#> 1     2008      32
#> 2     2011      44
#> 3     2007      28
#> 4     2011      44
#> 5     2001       4
#> 6     2010      40
#> 7     2000       0
#> 8     2007      28
#> 9     2000       0
#> 10    2002       8

reprex package(v0.3.0)于2019-11-06创建

答案 4 :(得分:-1)

考虑到OP的注释,您可以编写一个函数(概率为this answer):

library(tidyverse)
letter2num <- function(x) {(utf8ToInt(x) - utf8ToInt("a")) * 2}
tibble(x = letters) %>% 
  rowwise() %>% 
  mutate(y = letter2num(x))