使用case_when和startsWith选择性地按行更改

时间:2019-09-29 16:23:19

标签: r dplyr

我正在尝试基于另一列创建新列,使用case_when根据每一行的值提供不同的输出。

我从df <- data.frame(a=c("abc", "123", "abc", "123"))开始

并希望像这样生成新列b

#>     a      b
#> 1 abc letter
#> 2 123 number
#> 3 abc letter
#> 4 123 number

我已经尝试过df %>% mutate(b = case_when(startsWith(a, "a") ~ "letter", startsWith(a, "1") ~ "number")),但只给出了一个错误。有人可以告诉我如何根据a列中行的第一个字母为b列获取不同的值吗?

2 个答案:

答案 0 :(得分:1)

根据?startsWith

  

x-被视为“开始”的字符串的向量。

因此,startsWith期望该类为character,这里是factor类。将其转换为character类可以解决问题

library(dplyr)
df %>%
      mutate(b = case_when(startsWith(as.character(a), "a") ~ "letter",
                 TRUE ~ "number"))
#    a      b
#1 abc letter
#2 123 number
#3 abc letter
#4 123 number

data.frame的默认行为是stringsAsFactors = TRUE。如果我们指定stringsAsFactors = FALSE,则'a'列将为character


另一种选择是str_detect,可通过检查字符串开头(^)的字符是否是数字([0-9])来创建逻辑表达式

library(stringr)
library(dplyr)
df %>% 
    mutate(b = c("letter", "number")[1+str_detect(a, "^[0-9]")])
#    a      b
#1 abc letter
#2 123 number
#3 abc letter
# 123 number

答案 1 :(得分:0)

由于这里只有两种情况,因此您只能使用if_else()。考虑到您要运行的测试,正则表达式似乎更合适。关键是^指定字符串的开头,[:alpha:]匹配不区分大小写的字母。

library(tidyverse)

df <- data.frame(a=c("abc", "123", "abc", "123"))

df %>% mutate(
  b = a %>% str_detect("^[:alpha:]") %>% if_else("letter", "number")
)
#>     a      b
#> 1 abc letter
#> 2 123 number
#> 3 abc letter
#> 4 123 number

reprex package(v0.3.0)于2019-09-29创建

正如@akrun指出的那样,因素与字符之间存在问题-您确定这是适用于您的用例的示例,即您的真实数据是否在因素中?幸运的是,str_detect()的任何一种方式都一样好。