【问题标题】:Counting month name occurrences in R dataframe column计算 R 数据框列中出现的月份名称
【发布时间】:2021-05-31 01:33:29
【问题描述】:

我有一个这样的数据框

from <- c('Bob', 'Matt', 'Bob', 'Bob', 'Matt', 'Bob', 'Matt')
subject <- c('See you in June', 'Funny cat video', 'Plans for December', 'Re: Plans for December', 'Re:Re: Plans for December','November sales', 'Out of office in November')

df <- data.frame(from, subject)

  from                   subject
1  Bob           See you in June
2 Matt           Funny cat video
3  Bob        Plans for December
4  Bob    Re: Plans for December
5 Matt Re:Re: Plans for December
6  Bob            November sales
7 Matt Out of office in November

我想根据内置的month.name 向量在subject 中以字符串形式查找月份名称的出现

 [1] "January"   "February"  "March"     "April"     "May"       "June"      "July"     
 [8] "August"    "September" "October"   "November"  "December" 

然后将它们按from 值和月份相加。我想得到这样的结果:

from    month counts
1  Bob     June      1
2  Bob November      1
3 Matt November      1
4  Bob December      2
5 Matt December      1

我的猜测是我需要像下面这样使用str_count,但我不知道如何用from 中的名称来计数。

df %>%
  mutate(counts = str_count(subject, month.name)

【问题讨论】:

  • 首先使用 str_extract 创建您的月份列,然后是 groupby,然后是 summarise
  • 同一个字符串中是否有可能出现多个月份?

标签: r string tidyverse


【解决方案1】:

使用regmatches + subset + aggregate 的基本 R 选项

aggregate(
  n ~ from + months,
  subset(
    transform(
      df,
      months = unlist(
        replace(
          u <- regmatches(subject, gregexpr(paste0(month.name, collapse = "|"), subject)),
          lengths(u) == 0,
          NA
        )
      ),
      n = 1
    ),
    !is.na(months)
  ), sum
)

给予

  from   months n
1  Bob December 2
2 Matt December 1
3  Bob     June 1
4  Bob November 1
5 Matt November 1

【讨论】:

    【解决方案2】:

    另一种解决方案

    library(tidyverse)
    from <- c('Bob', 'Matt', 'Bob', 'Bob', 'Matt', 'Bob', 'Matt')
    subject <- c('See you in June', 'Funny cat video', 'Plans for December', 'Re: Plans for December', 'Re:Re: Plans for December','November sales', 'Out of office in November')
    
    df <- data.frame(from, subject)
    df %>% 
      group_by(from) %>% 
      mutate(month = map(strsplit(subject, split = " "), ~intersect(.x, month.name))) %>% 
      unnest(month) %>% 
      count(from, month)
    #> # A tibble: 5 x 3
    #> # Groups:   from [2]
    #>   from  month        n
    #>   <chr> <chr>    <int>
    #> 1 Bob   December     2
    #> 2 Bob   June         1
    #> 3 Bob   November     1
    #> 4 Matt  December     1
    #> 5 Matt  November     1
    

    reprex package (v1.0.0) 于 2021-03-01 创建

    使用 data.table

    
    library(data.table)
    
    setDT(df)[, list(from, month = unlist(tstrsplit(subject, split = " ")))][month %in% month.name][, .N, by = list(from, month)]
    #>    from    month N
    #> 1:  Bob November 1
    #> 2:  Bob December 2
    #> 3:  Bob     June 1
    #> 4: Matt December 1
    #> 5: Matt November 1
    

    reprex package (v1.0.0) 于 2021-03-01 创建

    【讨论】:

      【解决方案3】:

      这是一个解决方案,使用 str_extract_all,然后在 data.frame 中处理一些列表:

      library(tidyverse)
      
      df %>%
          rowwise() %>%
          mutate(months = list(str_extract_all(subject, month.name))) %>%
          unnest(months) %>%
          rowwise() %>%
          filter(length(months) > 0) %>%
          unnest(months) %>%
          count(from, months)
      
      #   from  months       n
      # 1 Bob   December     2
      # 2 Bob   June         1
      # 3 Bob   November     1
      # 4 Matt  December     1
      # 5 Matt  November     1
      

      【讨论】:

        【解决方案4】:

        基础 R 解决方案:

        subset(
          aggregate(ctr ~ from + months_,
           transform(
             data.frame(do.call(rbind, Map(
               function(y, z) {
                 cbind(from = y, months_ = z)
               },
               df$from,
               apply(do.call(rbind, lapply(month.name, function(w) {
                 grepl(w, df$subject)
               })), 2, function(x) {
                 if (sum(x) == 0) {
                   ""
                 } else{
                   month.name[x]
                 }
               })
             )),
             stringsAsFactors = FALSE), ctr = 1
           ), sum), 
          months_ !=  "")
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-10-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-04-20
          相关资源
          最近更新 更多