多条件 `rowSums`

Multiple condition `rowSums`

我想根据多个列(即多个条件)的特定值执行 rowSums。我知道如何 rowSums 基于单个条件(参见下面的示例)但似乎无法弄清楚多个条件。

# rowSums with single, global condition
set.seed(100)
df <- data.frame(a = sample(0:100,10),
             b = sample(0:100,10),
             c = sample(0:100,10),
             d = sample(0:100,10))
print(df)
   a   b  c  d 
1  31  63 54 49
2  25  88 71 92
3  54  27 53 34
4   5  39 73 93
5  45  73 40 67
6  46  64 16 85
7  77  19 97 17
8  34  33 82 59
9  50  93 51 99
10 15 100 25 11

单一条件有效

df$ROWSUMS <- rowSums(df[,1:4] <= 50)

# And produces 
   a   b  c  d ROWSUMS
1  31  63 54 49       2
2  25  88 71 92       1
3  54  27 53 34       2
4   5  39 73 93       2
5  45  73 40 67       2
6  46  64 16 85       2
7  77  19 97 17       2
8  34  33 82 59       2
9  50  93 51 99       1
10 15 100 25 11       3

多个条件不起作用

df$ROWSUMS_Multi <- rowSums(df[,1] <= 50 | df[,2] <= 25 | df[,3] <= 75)

Error in rowSums(df[, 1] <= 50 | df[, 2] <= 25 | df[, 3] <= 75) : 'x' must be an array of at least two dimensions

期望输出

   a   b  c  d ROWSUMS_Multi
1  31  63 54 49       2
2  25  88 71 92       2
3  54  27 53 34       1
4   5  39 73 93       2
5  45  73 40 67       2
6  46  64 16 85       2
7  77  19 97 17       1
8  34  33 82 59       1
9  50  93 51 99       2
10 15 100 25 11       2

我可能只是子设置不正确,但我一直无法找到修复方法。

[ 在具有单行或单列时的一个问题是它将 data.frame 强制转换为向量。基于 ?Extract

x[i, j, ... , drop = TRUE]

注意,drop 默认为 TRUE

及后面的文档

drop - For matrices and arrays. If TRUE the result is coerced to the lowest possible dimension (see the examples). This only works for extracting elements, not for the replacement. See drop for further details.

为了避免使用 drop = FALSE 或简单地删除 , 这将 return 一个列 data.frame 因为默认情况下,没有任何逗号的索引被视为作为 data.frame

的列索引而不是行索引
rowSums(df[1] <= 50 | df[2] <= 25 | df[3] <= 75)

更新

根据预期输出,rowSums 可以写成

dfROWSUMS <- rowSums(df[1:3] <= c(50, 25, 75)[col(df[1:3])])
df$ROWSUMS
#[1] 2 2 1 2 2 2 1 1 2 2

注意:之前的评论是基于 rowSums 不起作用的原因。之前没有检查预期的输出。在这里,我们需要比较具有不同值的 3 列。当我们这样做时

df[1] <= 50

是单列一个TRUE/FALSE

当我们 |

df[1] <= 50 | df[2] <= 25

它仍然是 TRUE/FALSE 的单列。唯一不同的是,我们将连续的 TRUE/FALSEFALSE/TRUE 替换为 TRUE。同样,当我们添加 n| 相比的逻辑比较时,情况也会如此。取而代之的是,做一个+,做元素总和

((df[1] <= 50)+ (df[2] <= 25) + (df[3] <= 75))[,1] # note it is a matrix

在这里,我们可以用 vector 来做到这一点,即也可以使用 ,

((df[, 1] <= 50)+ (df[, 2] <= 25) + (df[, 3] <= 75)) # vector output

唯一的问题是重复执行 +。如果我们使用rowSums,那么确保比较值复制(col)到data.frame子集的相同维度。另一种选择是 Map,

Reduce(`+`, Map(`<=`, df[1:3], c(50, 25, 75)))

我们还可以使用 cbind 使用列位置或列名从多个条件创建矩阵,然后像往常一样使用 rowSums,例如

> rowSums(cbind(df[,'a'] <= 50 ,df[,'b'] <= 25 ,df[,'c'] <= 75), na.rm = TRUE)
[1] 2 2 1 2 2 2 1 1 2 2

> rowSums(cbind(df['a'] <= 50 ,df['b'] <= 25 ,df['c'] <= 75), na.rm = TRUE)
[1] 2 2 1 2 2 2 1 1 2 2

使用dplyr

library(dplyr)
df %>% mutate(ROWSUMS=rowSums(cbind(.['a'] <= 50 ,.['b'] <= 25 ,.['c'] <= 75), na.rm = TRUE))