使用dplyr计算行中的值数

C_Z*_*_Z_ 5 r dplyr

这个问题应该有一个简单,优雅的解决方案,但我无法弄明白,所以这里有:

假设我有以下数据集,并且我想使用dplyr计算每行中存在的2的数量.

set.seed(1)
ID <- LETTERS[1:5]
X1 <- sample(1:5, 5,T)
X2 <- sample(1:5, 5,T)
X3 <- sample(1:5, 5,T)

df <- data.frame(ID,X1,X2,X3)
library(dplyr)
Run Code Online (Sandbox Code Playgroud)

现在,以下工作:

df %>%
  rowwise %>%
  mutate(numtwos = sum(c(X1,X2,X3) == 2))
Run Code Online (Sandbox Code Playgroud)

但是,如何避免键入所有列名称?

我知道这可能是不容易做到dplyr的,但更普遍的,我想知道我怎么可以使用dplyrmutate多列没有打字了所有列名.

eva*_*man 12

试试rowSums:

> set.seed(1)
> ID <- LETTERS[1:5]
> X1 <- sample(1:5, 5,T)
> X2 <- sample(1:5, 5,T)
> X3 <- sample(1:5, 5,T)
> df <- data.frame(ID,X1,X2,X3)
> df
  ID X1 X2 X3
1  A  2  5  2
2  B  2  5  1
3  C  3  4  4
4  D  5  4  2
5  E  2  1  4
> rowSums(df == 2)
[1] 2 1 0 1 1
Run Code Online (Sandbox Code Playgroud)

或者,用dplyr:

> df %>% mutate(numtwos = rowSums(. == 2))
  ID X1 X2 X3 numtwos
1  A  2  5  2       2
2  B  2  5  1       1
3  C  3  4  4       0
4  D  5  4  2       1
5  E  2  1  4       1
Run Code Online (Sandbox Code Playgroud)


Ste*_*pré 5

这是另一种替代方案purrr:

library(purrr)

df %>%
  by_row(function(x) {
    sum(x[-1] == 2) },
    .to = "numtwos",
    .collate = "cols"
  )
Run Code Online (Sandbox Code Playgroud)

这使:

#Source: local data frame [5 x 5]
#
#      ID    X1    X2    X3 numtwos
#  <fctr> <int> <int> <int>   <int>
#1      A     2     5     2       2
#2      B     2     5     1       1
#3      C     3     4     4       0
#4      D     5     4     2       1
#5      E     2     1     4       1
Run Code Online (Sandbox Code Playgroud)

正如新闻中所提到的,基于行的功能仍然在成熟dplyr:

我们仍然在弄清楚属于dplyr什么和属于什么 purrr.期待很多实验和这些功能的许多变化.


基准

我们可以看到如何rowwise()do()比较purrr::by_row()这类问题以及它们如何"执行" rowSums()以及整洁的数据方式:

largedf <-  df[rep(seq_len(nrow(df)), 10e3), ]

library(microbenchmark)
microbenchmark(
  steven = largedf %>% 
    by_row(function(x) { 
      sum(x[-1] == 2) }, 
      .to = "numtwos", 
      .collate = "cols"),
  psidom = largedf %>% 
    rowwise %>% 
    do(data_frame(numtwos = sum(.[-1] == 2))) %>% 
    cbind(largedf, .),
  gopala = largedf %>% 
    gather(key, value, -ID) %>% 
    group_by(ID) %>% 
    summarise(numtwos = sum(value == 2)) %>% 
    inner_join(largedf, .),
  evan   = largedf %>% 
    mutate(numtwos = rowSums(. == 2)),
  times  = 10L,
  unit   = "relative"
)
Run Code Online (Sandbox Code Playgroud)

结果:

#Unit: relative
#   expr         min          lq        mean      median         uq         max neval cld
# steven 1225.190659 1261.466936 1267.737126 1227.762573 1276.07977 1339.841636    10  b 
# psidom 3677.603240 3759.402212 3726.891458 3678.717170 3728.78828 3777.425492    10   c
# gopala    2.715005    2.684599    2.638425    2.612631    2.59827    2.572972    10 a  
#   evan    1.000000    1.000000    1.000000    1.000000    1.00000    1.000000    10 a  
Run Code Online (Sandbox Code Playgroud)

  • 这看起来很苛刻 (3认同)

bro*_*l23 5

只是想添加到@evan.oman 的答案中,以防您只想对特定列的行而不是所有列求和。您可以使用常规select和/或select_helpers函数。在这个例子中,我们不想包含X1rowSums

df %>% 
  mutate(numtwos = rowSums(select(., -X1) == 2))

  ID X1 X2 X3 numtwos
1  A  2  5  2       1
2  B  2  5  1       0
3  C  3  4  4       0
4  D  5  4  2       1
5  E  2  1  4       0
Run Code Online (Sandbox Code Playgroud)