2017-07-25 242 views
1

我正在使用R中的Retrosheet棒球数据,并试图创建一个单独的列(使用dplyr中的mutate函数),提醒我现有列中的单个字符串是否以“两击”或“三球”。例如:替代嵌套,如果其他语句

PITCH_SEQ_TX <- c('SSSC', 'FFBB', 'BBSSC', 'BBBSB', 'CBSFFFS') 

Retrosheet开发商只列出一个字符为球( “B”),但是几个用于打击(即, “C”, “F”, “升”, “M”, “S”, “T”)。因此,如果我想从上面的线,序列始于二罢工或三个球收集我会用:

PITCH_SEQ_TX_Updated <- mutate(PITCH_SEQ_TX, Cutoff = ifelse(grepl("^BBB", PITCH_SEQ_TX), 
"Three Balls", ifelse(grepl("^SS", updated_PITCH_SEQ_TX), "Two Strikes", 
ifelse(grepl("^FF", PITCH_SEQ_TX), "Two Strikes", "NA")))) 

无论其有两个罢工计数(太多不同的组合即CC,CS,FF等),这阻止了我在整个数据集上使用嵌套的if else语句(当通过50个不同的组合时,我得到一个错误:在第17行的上下文栈溢出警告)。是否有一个替代函数可以让我压缩现有代码,无论是使用ifelse还是其他一些函数来解决这个问题?任何帮助,将不胜感激。

+0

'?switch'可以帮助 –

+3

或'case_when',如果你想用'mutate'来做。 – mt1022

回答

2

您可以用方括号内指定它们使用的字符集的正则表达式为你的罢工标识符像[ABC],这将匹配任何字符AB,或C。这意味着你不必分别写出每个类别。例如: -

grepl("^[CFLMST]{2,}", PITCH_SEQ_TX) 
#[1] TRUE TRUE FALSE FALSE FALSE 
grepl("^B{3,}", PITCH_SEQ_TX) 
#[1] FALSE FALSE FALSE TRUE FALSE 
1

大厦@thelatemail's答案,与@mt1022's注释结合使用case_whenmutate,这里是整个例子,使用函数从stringr文本的工作。

library(dplyr) 
library(stringr) 

# make vector of pitch sequence data 
PITCH_SEQ_TX <- c('SSSC', 'FFBB', 'BBSSC', 'BBBSB', 'CBSFFFS') 

# make another variable of the number of pitches in each sequence 
# this is just so we have two variables for a df 
NUM_PITCHES <- stringr::str_count(PITCH_SEQ_TX) 

# make a df 
BB <- dplyr::tibble(PITCH_SEQ_TX, NUM_PITCHES) 

# create the recoded pitch sequence variable - PITCH_SEQ_TX_UPDATED 
BB %>% 
    dplyr::mutate(PITCH_SEQ_TX_UPDATED = 
       dplyr::case_when(
        stringr::str_detect(string = PITCH_SEQ_TX, pattern = "^[CFLMST]{2,}") ~ "Two strikes", 
        stringr::str_detect(string = PITCH_SEQ_TX, pattern = "^B{3,}") ~ "Three balls" 
        ) 
    ) 

# A tibble: 5 x 3 
    PITCH_SEQ_TX NUM_PITCHES PITCH_SEQ_TX_UPDATED 
     <chr>  <int>    <chr> 
1   SSSC   4   Two strikes 
2   FFBB   4   Two strikes 
3  BBSSC   5     <NA> 
4  BBBSB   5   Three balls 
5  CBSFFFS   7     <NA>