【问题标题】:Mutate changes full column instead of row by row变异改变整列而不是逐行
【发布时间】:2020-05-18 23:36:29
【问题描述】:

在数据框中,我想根据另一列中出现的一组特定字符串(字符向量)创建一个新列。

所以基本上,我想要这个:

ID  Phrases
1   some words
2   some words dec
3   some words nov may

返回这个:

ID  Phrases             MonthsOccur
1   some words          NA
2   some words dec      dec
3   some words nov may  may nov

我已经尝试了以下方法,但我不确定为什么它会给我这样的结果:

library(dplyr)

vMonths <- c("jan","feb","mar","apr","may","jun","jul","aug","sept","nov","dec")

a <- c(1,2,3)
b <- c('phrase number one', 'phrase dec','phrase nov')

df <- data.frame(a,b)
names(df) <- c("ID","Phrases")
df <- df %>% mutate(MonthsOccur = paste(vMonths[str_detect(Phrases, vMonths)],collapse=" "))

它给了我以下警告:

警告信息: 在 stri_detect_regex(string, pattern, negate = negate, opts_regex = opts(pattern)) 中: 较长的对象长度不是较短对象长度的倍数

结果如下:

ID  Phrases             MonthsOccur
1   some words          dec
2   some words dec      dec
3   some words nov may  dec

【问题讨论】:

  • 旁注:tolower(month.abb)

标签: r regex dplyr stringr


【解决方案1】:

涉及dplyrstringr 的另一个选项可能是:

df %>%
 mutate(MonthsOccur = str_extract_all(Phrases, paste(tolower(month.abb), collapse = "|")))

  ID            Phrases MonthsOccur
1  1         some words            
2  2     some words dec         dec
3  3 some words nov may    nov, may

这里输出的不是字符向量,而是列表。

如果你确实在寻找一个字符向量,那么加上purrr:

df %>%
 mutate(MonthsOccur = map_chr(str_extract_all(Phrases, paste(tolower(month.abb), collapse = "|")), 
                              paste, collapse = ", "))

【讨论】:

    【解决方案2】:

    一种选择是申请str_detectrowwise

    library(dplyr)
    library(stringr)
    
    df %>%
      rowwise() %>%
      mutate(MonthsOccur = paste0(vMonths[str_detect(Phrases, vMonths)], 
                           collapse = " "))
    

    但是,rowwise 将来可能会或可能不会继续,因此更好的方法是使用 map 操作

    df %>%
      mutate(MonthsOccur = purrr::map_chr(Phrases,  
                          ~paste0(vMonths[str_detect(.x, vMonths)], collapse = " ")))
    
    #  ID           Phrases MonthsOccur
    #1  1 phrase number one            
    #2  2        phrase dec         dec
    #3  3    phrase nov may     may nov
    

    基本 R 选项将与 regmatchesgregexpr 一起使用

    sapply(regmatches(df$Phrases, gregexpr(paste0(vMonths, collapse = "|"),
            df$Phrases)), paste0, collapse = " ")
    

    数据

    df <- structure(list(ID = c(1, 2, 3), Phrases = structure(c(3L, 1L, 
    2L), .Label = c("phrase dec", "phrase nov may", "phrase number one"
    ), class = "factor")), class = "data.frame", row.names = c(NA, -3L))
    

    【讨论】:

    • 谢谢——就像一个魅力!关于为什么这似乎与mutate 中使用的其他功能不同的任何见解(无论如何它们似乎都在逐行工作)?似乎无法弄清楚它为什么会这样做。
    • @BroQ 很好,这是因为str_detectstringpattern 上进行了矢量化。所以Phrases[1]vMonths[1]比较,Phrases[2]vMonths[2]比较。所以你不会得到你所期待的所有比赛。通过指定rowwise 或使用map,我们将Phrases[1] 与所有vMonths 进行比较,然后将Phrases[2] 与所有vMonths 进行比较,依此类推。
    猜你喜欢
    • 1970-01-01
    • 2018-11-30
    • 1970-01-01
    • 2017-10-26
    • 2018-12-07
    • 1970-01-01
    • 2021-11-21
    • 1970-01-01
    • 2019-10-29
    相关资源
    最近更新 更多