多条件行和

时间:2019-04-19 17:28:31

标签: r conditional

我想基于多个列(即多个条件)的特定值执行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)
  

rowSums(df [,1] <= 50 | df [,2] <= 25 | df [,3] <= 75)中的错误:     “ x”必须是至少二维的数组

所需的输出

   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

我可能只是错误地设置了子设置,但我无法找到修复程序。

2 个答案:

答案 0 :(得分:4)

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

  

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

注意,drop默认为TRUE

以及随后的文档中

  

drop-用于矩阵和数组。如果为TRUE,则结果强制为最小尺寸(请参见示例)。这仅适用于提取元素,不适用于替换。有关更多详细信息,请参见drop。

为避免这种情况,请使用drop = FALSE或简单地删除,,这将返回单个列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/FALSE连续替换了FALSE/TRUETRUE。同样,与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)))

答案 1 :(得分:1)

我们还可以使用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))