【问题标题】:Count occurrence of string values per row in dataframe in R (dplyr)计算 R (dplyr) 中数据帧中每行字符串值的出现次数
【发布时间】:2021-09-29 04:17:36
【问题描述】:

我希望计算数据框中每行选择字符串值的出现次数。理想情况下,这将使用dplyr 包完成。

这是一个类似于我正在使用的数据框:

df <- tibble(
  d1 = c('b', 'a', 'a', 'a', 'a', 'a', 'a', 'a'),
  d2 = c('a', 'a', 'b', 'a', 'a', 'a', 'a', 'a'),
  d3 = c('a', 'a', 'a', 'c', 'a', 'b', 'a', 'a'),
  d4 = c('a', 'a', 'a', 'a', 'a', 'a', 'a', 'd'),
  d5 = c('a', 'c', 'a', 'a', 'a', 'a', 'a', 'a'),
  d6 = c('a', 'a', 'a', 'b', 'a', 'a', 'd', 'a'),
  d7 = c('a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'),
  d8 = c('a', 'a', 'a', 'a', 'a', 'a', 'a', 'a')
)

我希望能够定义我正在计算的列:

cols <- c('d2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8')

我还想定义我要搜索的字符串:

bcde <- c('b', 'c', 'd', 'e')

到目前为止,我已经能够使用以下代码确定bcde 中的一个字符串存在于每行d2:d8 之一中:

df <- df %>% 
  mutate(
    d9 = case_when(
      if_any(all_of(cols), ~ . %in% bcde) ~ 1,
      TRUE ~ 0)
  )

产生:

  d1    d2    d3    d4    d5    d6    d7    d8       d9
  <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
1 b     a     a     a     a     a     a     a         0
2 a     a     a     a     c     a     a     a         1
3 a     b     a     a     a     a     a     a         1
4 a     a     c     a     a     b     a     a         1
5 a     a     a     a     a     a     a     a         0
6 a     a     b     a     a     a     a     a         1
7 a     a     a     a     a     d     a     a         1
8 a     a     a     d     a     a     a     a         1

但是,我想制作:

  d1    d2    d3    d4    d5    d6    d7    d8       d9
  <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
1 b     a     a     a     a     a     a     a         0
2 a     a     a     a     c     a     a     a         1
3 a     b     a     a     a     a     a     a         1
4 a     a     c     a     a     b     a     a         2
5 a     a     a     a     a     a     a     a         0
6 a     a     b     a     a     a     a     a         1
7 a     a     a     a     a     d     a     a         1
8 a     a     a     d     a     a     a     a         1

(即,如果在 cols d2:d8 中出现 bcde 中的字符串,则计算出现次数,而不是仅仅检查它们是否存在)。

我不确定如何在循环遍历数据帧时加入计数功能。

谢谢!

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    您可以将acrossrowSums 一起使用-

    library(dplyr)
    
    df %>% mutate(d9 = rowSums(across(all_of(cols), `%in%`, bcde)))
    
    #  d1    d2    d3    d4    d5    d6    d7    d8       d9
    #  <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
    #1 b     a     a     a     a     a     a     a         0
    #2 a     a     a     a     c     a     a     a         1
    #3 a     b     a     a     a     a     a     a         1
    #4 a     a     c     a     a     b     a     a         2
    #5 a     a     a     a     a     a     a     a         0
    #6 a     a     b     a     a     a     a     a         1
    #7 a     a     a     a     a     d     a     a         1
    #8 a     a     a     d     a     a     a     a         1
    

    这也可以写成base R -

    df$d9 <- rowSums(sapply(df[cols], `%in%`, bcde))
    

    【讨论】:

    • 非常有帮助,谢谢!
    【解决方案2】:

    这也可以在带有轴方向applyaxis2 的基础 R 中完成:

    df$d9 <- rowSums(apply(df[cols], 2, `%in%`, bcde))
    

    现在:

    df
    

    给予:

      d1    d2    d3    d4    d5    d6    d7    d8       d9
      <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
    1 b     a     a     a     a     a     a     a         0
    2 a     a     a     a     c     a     a     a         1
    3 a     b     a     a     a     a     a     a         1
    4 a     a     c     a     a     b     a     a         2
    5 a     a     a     a     a     a     a     a         0
    6 a     a     b     a     a     a     a     a         1
    7 a     a     a     a     a     d     a     a         1
    8 a     a     a     d     a     a     a     a         1
    

    【讨论】:

      【解决方案3】:

      我们可能会使用

      library(purrr)
      library(dplyr)
      df %>%
          mutate(d9 = across(all_of(cols), `%in%`, bcde) %>% 
              reduce(`+`))
      # A tibble: 8 × 9
        d1    d2    d3    d4    d5    d6    d7    d8       d9
        <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <int>
      1 b     a     a     a     a     a     a     a         0
      2 a     a     a     a     c     a     a     a         1
      3 a     b     a     a     a     a     a     a         1
      4 a     a     c     a     a     b     a     a         2
      5 a     a     a     a     a     a     a     a         0
      6 a     a     b     a     a     a     a     a         1
      7 a     a     a     a     a     d     a     a         1
      8 a     a     a     d     a     a     a     a         1
      

      【讨论】:

        【解决方案4】:

        这是一个 dplyr-esque,后跟一个仅使用 dplyr 的替代方案:

        library(tidyverse)
        
        df <- tibble(
          d1 = c('b', 'a', 'a', 'a', 'a', 'a', 'a', 'a'),
          d2 = c('a', 'a', 'b', 'a', 'a', 'a', 'a', 'a'),
          d3 = c('a', 'a', 'a', 'c', 'a', 'b', 'a', 'a'),
          d4 = c('a', 'a', 'a', 'a', 'a', 'a', 'a', 'd'),
          d5 = c('a', 'c', 'a', 'a', 'a', 'a', 'a', 'a'),
          d6 = c('a', 'a', 'a', 'b', 'a', 'a', 'd', 'a'),
          d7 = c('a', 'a', 'a', 'a', 'a', 'a', 'a', 'a'),
          d8 = c('a', 'a', 'a', 'a', 'a', 'a', 'a', 'a')
        )
        
        cols <- c('d2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8')
        bcde <- c('b', 'c', 'd', 'e')
        
        t(df) %>%
         as.data.frame() -> dft
        
        dft[cols, ] %>% 
          map_dbl(~. %in% bcde %>% sum) %>%
          {mutate(df, d9 = .)}
        #> # A tibble: 8 × 9
        #>   d1    d2    d3    d4    d5    d6    d7    d8       d9
        #>   <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
        #> 1 b     a     a     a     a     a     a     a         0
        #> 2 a     a     a     a     c     a     a     a         1
        #> 3 a     b     a     a     a     a     a     a         1
        #> 4 a     a     c     a     a     b     a     a         2
        #> 5 a     a     a     a     a     a     a     a         0
        #> 6 a     a     b     a     a     a     a     a         1
        #> 7 a     a     a     a     a     d     a     a         1
        #> 8 a     a     a     d     a     a     a     a         1
        
        
        #We can also do a `rowwise()` approach.
        
        bcde_present <- function(x) {
          x %in% bcde 
        }
        
        #regular expression to match the desired columns in case they don't appear in order.
        
        df %>% 
          rowwise() %>% 
          mutate(d9 = sum(bcde_present(across(matches('d[2-8]')))))
        #> # A tibble: 8 × 9
        #> # Rowwise: 
        #>   d1    d2    d3    d4    d5    d6    d7    d8       d9
        #>   <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <int>
        #> 1 b     a     a     a     a     a     a     a         0
        #> 2 a     a     a     a     c     a     a     a         1
        #> 3 a     b     a     a     a     a     a     a         1
        #> 4 a     a     c     a     a     b     a     a         2
        #> 5 a     a     a     a     a     a     a     a         0
        #> 6 a     a     b     a     a     a     a     a         1
        #> 7 a     a     a     a     a     d     a     a         1
        #> 8 a     a     a     d     a     a     a     a         1
        

        reprex package (v2.0.1) 于 2021 年 9 月 29 日创建

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-15
          • 2021-08-02
          • 1970-01-01
          • 1970-01-01
          • 2016-01-23
          • 1970-01-01
          相关资源
          最近更新 更多