2

来自其他各种语言,我发现 R 功能强大且直观,但我对它的性能并不感到兴奋。所以我决定尝试改进我编写的一些代码片段,并学习如何更好地在 R 中编写代码。

这是我写的一个函数,试图确定一个向量是否是二进制值(两个不同的值或只有一个值):

isBinaryVector <- function(v) {
  if (length(v) == 0) {
    return (c(0, 1))
  }
  a <- v[1]
  b <- a
  lapply(v, function(x) { if (x != a && x != b) {if (a != b) { return (c()) } else { b = x }}})
  if (a < b) {
    return (c(a, b))
  } else {
    return (c(b, a))
  }
}

编辑:这个函数应该查看一个向量,然后c()如果它不是二进制值则返回,c(a, b)如果是,则返回,a 是较小的值,b 是较大的值(如果 a == b 则只是c(a, a)。例如,对于

  A B C
1 1 1 0
2 2 2 0
3 3 1 0

我会这样做lapplyisBinaryVector得到:

$A
[1] 1 1

$B
[1] 1 1

$C
[1] 0 0

在中等大小的数据集(大约 1800 * 3500,其中 2/3 是二进制值)上花费的时间大约是 15 秒。该集合仅包含浮点数。

无论如何我可以更快地做到这一点吗?

感谢您的任何投入!

4

2 回答 2

8

您实际上是在尝试编写一个函数,如果向量恰好具有两个唯一值,则该函数返回 TRUE,否则返回 FALSE。

试试这个:

> dat <- data.frame(
+   A = 1:3,
+   B = c(1, 2, 1), 
+   C = 0
+ )
> 
> sapply(dat, function(x)length(unique(x))==2)
    A     B     C 
FALSE  TRUE FALSE 

接下来,您要获取最小值和最大值。该函数range执行此操作。所以:

> sapply(dat, range)
     A B C
[1,] 1 1 0
[2,] 3 2 0

在那里,你拥有了制作一个易于理解并且应该非常快速的小函数的所有要素,即使是在大量数据上:

isBinary <- function(x)length(unique(x))==2

binaryValues <- function(x){
  if(isBinary(x)) range(x) else NA
}

sapply(dat, binaryValues)

$A
[1] NA

$B
[1] 1 2

$C
[1] NA
于 2012-04-19T14:52:02.270 回答
4

此函数为向量(或数据框的列)返回 true 或 false:

is.binary <- function(v) {
  x <- unique(v)
  length(x) - sum(is.na(x)) == 2L
}

也看看这个帖子

我会使用类似的东西来获取列索引:

bivalued <- apply(my.data.frame, 2, is.binary)

nominal <- my.data.frame[,!bivalued]
binary <- my.data.frame[,bivalued]

样本数据:

my.data.frame <- data.frame(c(0,1), rnorm(100), c(5, 19), letters[1:5], c('a', 'b'))
> apply(my.data.frame, 2, is.binary)
     c.0..1.   rnorm.100.     c.5..19. letters.1.5.  c..a....b.. 
        TRUE        FALSE         TRUE        FALSE         TRUE 
于 2012-04-19T14:42:44.140 回答