【问题标题】:Counting (for each row) how many times an OR condition on several columns is satisfied计算(对于每一行)满足几列上的 OR 条件的次数
【发布时间】:2014-09-25 15:15:20
【问题描述】:

我的问题与this one 类似,只是有点不同。在最初的问题中,我试图计算(对于每一行)有多少列满足条件。我想做类似的事情,除了条件涉及带有 OR 条件的几列,而我的真实数据有很多列,所以理想情况下,我想使用正则表达式引用这些列。

我有以下数据:

colnames <- c(paste("col",rep(LETTERS[1:2],each=4),rep(1:4,2),sep=""),c("meh","muh"))
df <- as.data.frame(matrix(sample(c("Yes","No"),200,replace=TRUE),ncol=10))
names(df) <- colnames
df
   colA1 colA2 colA3 colA4 colB1 colB2 colB3 colB4 meh muh
1     No   Yes    No    No    No   Yes   Yes    No Yes Yes
2     No   Yes   Yes   Yes   Yes    No   Yes    No  No  No
3     No    No    No   Yes    No    No    No    No Yes  No
4    Yes    No   Yes   Yes   Yes   Yes   Yes   Yes  No Yes
5    Yes    No   Yes    No    No    No    No   Yes  No Yes
6    Yes    No    No    No   Yes   Yes    No    No  No  No
7    Yes    No    No    No   Yes   Yes   Yes    No Yes  No
8    Yes    No   Yes    No   Yes   Yes    No   Yes Yes  No
9     No   Yes    No    No    No   Yes   Yes    No  No  No
10   Yes   Yes    No    No   Yes    No   Yes    No Yes  No
11    No   Yes    No    No   Yes    No   Yes   Yes  No  No
12    No   Yes   Yes   Yes    No    No   Yes    No  No  No
13    No    No   Yes   Yes    No   Yes   Yes   Yes Yes  No
14   Yes   Yes    No    No    No    No   Yes    No  No Yes
15   Yes    No   Yes   Yes    No   Yes    No   Yes  No  No
16    No   Yes   Yes    No    No    No   Yes    No  No  No
17   Yes    No    No    No    No   Yes   Yes   Yes  No Yes
18   Yes    No   Yes   Yes    No    No    No    No  No Yes
19    No    No    No    No    No   Yes    No    No  No Yes
20    No   Yes    No    No   Yes   Yes   Yes    No  No  No

我想创建一个新列Nb,记录每一行:colA2、colA3、colA4 中至少一个为 =="Yes" 的次数加上 colB2 中至少一个的次数, colB3,colB4 为 =="Yes"。

如果在查看一组列 [colA2, colA3,colA4] 时没有暗示这个“或”条件,并且我正在添加满足条件的列数,我可以使用类似的东西:

df$Nb <- rowSums(df[, grep("^col[A-B][2-4]", names(df))] == "Yes")

如果可能,我想使用正则表达式来引用列,因为在我的真实数据中,字母和数字分别比 B 和 5 更远。

谢谢!

【问题讨论】:

  • 你能改变grep中的变量吗? grep('^col[A-N][2-30], names(df))?
  • 您真的应该将那些“是”/“否”值转换为逻辑值 (TRUE/FALSE)。
  • @maloneypatr 我可以,但是我写的表达式无法实现我想要的;相反,它只会计算 == "Yes" 的列数。
  • @Roland 这是个好主意。我正在使用df[, grep("^col[A-B][2-4]", names(df))] &lt;- (df[, grep("^col[A-B][2-4]", names(df))] == "Yes") 进行操作。是否有效(足够)?
  • @Peutch 是的,这很有效。但是为什么不对所有列都这样做呢?

标签: regex r dataframe conditional-statements


【解决方案1】:

您可以将 rowSums 方法调整为仅适用于每个 OR 条件中的列组,然后添加 &gt; 0 以使其“至少一个”。因此,“A 值中至少有一个是 Yes”看起来像:

rowSums(df[, grep("^colA[2-4]", names(df))] == "Yes") > 0

然后您可以使用+ 组合它们:

(rowSums(df[, grep("^colA[2-4]", names(df))] == "Yes") > 0) +
 (rowSums(df[, grep("^colB[2-4]", names(df))] == "Yes") > 0)

顺便说一句,如果您的数据位于 tidy format 中,您将更容易回答此类问题:也就是说,如果每列都是单独的变量。现在看起来您将数据的属性(A、B、1-4)存储为列名的一部分,这就是“使用值为'A'的列”之类的操作非常尴尬的原因。如果您改为使用 dplyr 和 tidyr 包重新排列数据会怎样:

library(dplyr)
library(tidyr)
df$index <- 1:nrow(df)
newdf <- df %>% gather(key, value, colA1:colB4) %>%
    separate(key, c("col", "letter", "number"), c(-3, -2)) %>%
    mutate(number = as.numeric(number))

这会将您的数据重新排列为(请注意,我为您的每一行提供了自己的“索引”变量):

  meh muh index col letter number value
1 Yes  No     1 col      A      1   Yes
2 Yes  No     2 col      A      1   Yes
3  No  No     3 col      A      1   Yes
4 Yes  No     4 col      A      1    No
5 Yes Yes     5 col      A      1    No
6 Yes Yes     6 col      A      1   Yes

然后,您可以更自然地对这些观察结果进行分组、总结、过滤和操作。例如,您似乎想删除编号为 1 的列:不需要正则表达式,您可以简单地执行 newdf %&gt;% filter(number &gt; 1)

您将如何执行您所描述的那种 OR 操作:

hasyes <- newdf %>% group_by(index, letter) %>% filter(number > 1) %>%
              summarize(hasyes = any(value == "Yes"))

对于每个原始的行+字母组合,您现在有一个逻辑值来判断Yes 是否出现:

  index letter hasyes
1     1      A   TRUE
2     1      B   TRUE
3     2      A   TRUE
4     2      B   TRUE
5     3      A  FALSE
6     3      B   TRUE

再进行一次汇总操作即可将其转换为您想要的形式:

result <- hasyes %>% group_by(index) %>% summarize(yeses = sum(hasyes))

此解决方案的重要之处在于它同样适用于您拥有的任意数量的字母(也就是说,如果它来自 A-Z 而不仅仅是 A 和 B)。

【讨论】:

  • 谢谢,这是一个聪明的方法。你是否有什么办法让我不必为每个字母 A、B 指定总和的项……在我的真实数据中,字母走得很远,所以写起来有点烦人每个项的总和。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-13
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 2020-10-10
  • 2013-10-14
相关资源
最近更新 更多