在R(dplyr)中计算数据框每行字符串值的出现次数

4

我希望能够使用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

我需要在遍历数据框时,将一个字符串在列d2:d8中出现的次数计算出来,而不是仅仅检查其是否存在(即在bcde中计算字符串出现的次数)。

我不确定如何同时使用循环和计数函数来实现这个功能。

谢谢!

4个回答

3
你可以使用rowSumsacross -
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

这也可以用基础的R语言编写 -

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

1
如果我想使用相同的代码,但是不指定特定的列,而是将函数应用于数据集的所有列,那么在“rowSums(across("?之后我应该写什么? - Brenda Thompson

1

这也可以在基础的R中通过轴向apply来完成,在axis 2上进行:

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

And now:

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

1
我们可以使用。
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

1

以下是一个类似于dplyr的示例,以及仅使用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

本文创建于2021-09-29,使用reprex包(版本2.0.1)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接