2016-07-09 85 views
0

我有一個功能,從文本字符串中提取月份,匹配特定的模式(如MAR06):只有[R發生變異不會返回函數值正確

library(dplyr) 
pattern <- "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\\d{2,2}" 

find_month <- function(x) 
{ 
extracted <- str_extract(x, pattern) 
month_string <- substr(extracted, 1, 3) 
if(!is.na(month_string) && month_string[[1]] == 'MAY') 
{ 
    value <- 1 
} 
else 
{ 
    value <- -1 
} 
return(value) 
} 

爲了簡化問題,我在這裏查看月份是否是五月份。 它,當我手動測試正常工作:

> find_month("HELLO THERE MAY06") 
[1] 1 
> find_month("BYE SEP12") 
[1] -1 

然而,當我把它放在一個數據幀,它總是爲每一行返回1:

a = c("HELLO THERE MAY06", "BYE SEP12") 
b = c(TRUE, FALSE) 
df = data.frame(desc=a, other=b) 

df_mutated <- mutate(df, month = find_month(desc)) 
df_mutated 
      desc other month 
1 HELLO THERE MAY06 TRUE  1 
2   BYE SEP12 FALSE  1 

我在做什麼錯?

+2

爲什麼不只需使用'grepl(「MAY」,「HELLO THERE MAY06」,fixed = TRUE)',並根據需要轉換爲數字?這會給1是肯定的,0沒有 –

+2

@RichardScriven:也許'grepl('MAY \\ d {2}',...)'以防止匹配,例如'MAYBE NOV07「'。 – jbaums

回答

1

要回答「我在做什麼錯」,你可以看看當你debugonce(find_month)會發生什麼。 mutate函數被矢量化,所以extracted將是一個匹配向量,而month_string將是月份名稱的向量。由於&&會返回長度爲1的矢量,因此您的代碼將返回1-1,具體取決於是否存在任何NA以及month_string的第一個元素是否爲'MAY'(因爲您使用的是month_string[[1]])。

find_month <- function(x) { 
    extracted <- str_extract(x, pattern) 
    month_string <- substr(extracted, 1, 3) 
    ifelse(!is.na(month_string) & month_string == 'MAY', 1, -1) 
} 

這就是說,理查德的suggestion使用grepl是明智的:

您可以通過替換您的ififelse vectorise你發生變異的功能。

0

假設你在desc列不同的名稱,你可以用rowwise()到非矢量化功能應用到每一行:

R> df_mutated2 <- df %>% group_by(desc) %>% rowwise() %>% mutate(month = find_month(desc)) 
R> df_mutated2 
Source: local data frame [2 x 3] 
Groups: <by row> 

       desc other month 
       (chr) (lgl) (dbl) 
1 HELLO THERE MAY06 TRUE  1 
2   BYE SEP12 FALSE -1 
1

我們可以使用str_detect

library(stringr) 
library(dplyr) 
df %>% 
    mutate(month = c(1, -1)[(str_detect(desc, "MAY")+1)]) 
#    desc other month 
#1 HELLO THERE MAY06 TRUE -1 
#2   BYE SEP12 FALSE  1