【问题标题】:Simplify a code in R简化 R 中的代码
【发布时间】:2017-11-17 17:52:40
【问题描述】:

我编写了一个代码,它遍历数据帧的列,如果其中任何一个列中有数字 1,则返回 TRUE,并将值发送到与数据帧的列大小相同的向量。我想知道是否有办法简化下面的代码 sn-p,因为我必须重复几个数字。

n1 <- (tab[, 2]==1|  tab[, 3]==1 | tab[, 4]==1 | tab[, 5]==1 | 
     tab[, 6]==1 | tab[, 7]==1 | tab[, 8]==1 | tab[, 9]==1 |
     tab[, 10]==1 | tab[, 11]==1 | tab[, 12]==1 | tab[, 13]==1 |
     tab[, 14]==1 | tab[, 15]==1 | tab[, 16]==1)

【问题讨论】:

  • 阅读 apply 系列函数。在您的 R 终端中输入 ?apply?lapply,欢迎来到 R 的世界!
  • IsraelMotta,提供的任何一个答案都可以解决您的问题吗?如果是这样,礼仪建议您通过选择特定答案左侧的复选标记来“接受”首选答案。 (如果没有,请提供反馈。)谢谢!

标签: r vector logical-operators


【解决方案1】:

一种可能的解决方案如下:在数据框中搜索 == 1 数字,然后使用 | 运算符减少该数字的行数:

tab <- data.frame(a = 1:10, b = 2:11)

apply(tab == 1, 1, function(x) {
  Reduce("|", x)
})

对于这个例子,它会给你输出:

[1]  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

或者一个更简单的解决方案是:

apply(tab, 1, function(x) {
  any(x == 1)
})

【讨论】:

  • rowSums(tab == 1) &gt; 0
  • applyrowSumsdata.frame 一起使用很草率且容易出错;如果您确信它是所有数字,那么它几乎没有理由成为matrix,因为这些功能可以完美运行。当您错误地在数据中包含非numeric 时,这两个函数都会中断和/或改变行为。 (在这种微不足道的情况下,简单的== 不一定会破坏,但我的前提是成立的。)
【解决方案2】:

其他 cmets 和答案可以工作,但我建议他们在处理 data.frame 时鼓励不良行为。首先也是最重要的是applyrowSums 期望matrix 作为数据,如果给定data.frame,他们会很高兴地强制这样。如果任何data.frame 列是character,则所有列都将转换为character。某些操作可能仍按预期工作(例如,== 1,因为它实际上将是 == "1" ...尽管一些舍入错误可能会导致不良影响),但任何数学运算都将不起作用。

举个例子

n <- 20
set.seed(2)
tab <- data.frame(
  a = as.character(sample(n, replace = FALSE)),
  b1 = sample(5, size = n, replace = TRUE),
  b2 = sample(5, size = n, replace = TRUE),
  stringsAsFactors = FALSE
)
str(tab)
# 'data.frame': 20 obs. of  3 variables:
#  $ a : chr  "4" "14" "11" "3" ...
#  $ b1: int  4 2 5 1 2 3 1 2 5 1 ...
#  $ b2: int  5 2 1 1 5 4 5 2 3 5 ...

apply(tab, 1, function(y) any(y == 1))
#  [1] FALSE FALSE  TRUE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE
apply(tab, 1, sum)
# Error in FUN(newX[, i], ...) : invalid 'type' (character) of argument

rowSums(tab == 1)
#  [1] 0 0 1 2 0 0 1 0 0 1 2 2 0 0 0 0 0 1 0 1
rowSums(tab)
# Error in rowSums(tab) : 'x' must be numeric

有一些简单的方法可以解决这个问题。鉴于您的示例,2:16 列似乎是数字的,并且您关注的列。如果是这种情况,那么您可以安全地使用以下任一种:

rowSums(tab[,2:16] == 1)                      # Frank's comment
apply(tab[,2:16], 1, function(y) any(y == 1)) # suggested by You-leee's answer

(前者相当具体,后者可以扩展到其他功能)。如果只有一个非numeric,一次总是可以的

rowSums(tab[,-1,drop=FALSE] == 1)
apply(tab[,-1,drop=FALSE], 1, function(y) any(y == 1))

第三种技术是在运行时确定选择哪些列:

isnum <- sapply(tab, is.numeric)
Reduce(`|`, lapply(tab[isnum], function(y) any(y == 1)))

这有点复杂,因为来自lapply 的返回是list,但它仍然可以正常工作。意识到isnum 的使用也可以基于列名,例如使用grepl。这种方法也相当健壮,因为如果没有任何列匹配,它也不会出错。

【讨论】:

  • 谢谢你,这对我帮助很大。该解决方案运行良好,因为它是一个数据框,我认为它是最安全的解决方案。
猜你喜欢
  • 2023-01-22
  • 1970-01-01
  • 2018-10-24
  • 1970-01-01
  • 2011-08-09
  • 2022-06-20
  • 2019-08-01
  • 2012-05-11
  • 1970-01-01
相关资源
最近更新 更多