【问题标题】:Convert numeric values into binary (0/1)将数值转换为二进制 (0/1)
【发布时间】:2013-01-09 16:33:16
【问题描述】:

我有一个数据框,其中包含不同人的不同种类水果的计数。如下所示

    apple  banana  orange
Tim     3       0       2
Tom     0       1       1
Bob     1       2       2

我怎样才能把它变成一个二进制矩阵,即如果一个人至少有一个水果,不管他有多少,那么我记录1,如果没有,记录0。如下所示

    apple  banana  orange
Tim     1       0       1
Tom     0       1       1
Bob     1       1       1

【问题讨论】:

  • 你的对象是矩阵还是数据框?如果它是包含所有数字信息的数据框,您可以使用as.matrix 将其强制转换为矩阵。
  • 这是一个带有标题的数据框

标签: r dataframe matrix binary


【解决方案1】:

这是你的data.frame

x <- structure(list(apple = c(3L, 0L, 1L), banana = 0:2, orange = c(2L, 
1L, 2L)), .Names = c("apple", "banana", "orange"), class = "data.frame", row.names = c("Tim", 
"Tom", "Bob"))

还有你的矩阵:

as.matrix((x > 0) + 0)
    apple banana orange
Tim     1      0      1
Tom     0      1      1
Bob     1      1      1

更新

我不知道睡前快速发帖会产生anydiscussion,但讨论本身很有趣,所以我想在这里总结一下:

我的直觉是简单地接受这样一个事实,即在 R 中的 TRUEFALSE 下方是数字 10。如果您尝试(一种不太好的方法)检查​​等价性,例如1 == TRUE0 == FALSE,您将得到TRUE。我的捷径(结果比正确花费更多时间,或者至少在概念上更正确方式)只是添加@987654333 @ 给我的TRUEs 和FALSEs,因为我知道 R 会将逻辑向量强制转换为数字。

正确的,或者至少更合适的方法是使用as.numeric 转换输出(我认为这是@JoshO'Brien 打算写的)。但是....不幸的是,这会删除输入的维度属性,因此您需要将结果向量重新转换为矩阵,事实证明,它仍然是 still 比我在回答中添加 0 更快。

阅读了 cmets 和批评后,我想我会再添加一个选项 --- 使用 apply 循环遍历列并使用 as.numeric 方法。这比手动重新创建矩阵,但比将0 添加到逻辑比较中略快

x <- data.frame(replicate(1e4,sample(0:1e3)))
library(rbenchmark)
benchmark(X1 = {
            x1 <- as.matrix((x > 0) + 0)
          },
          X2 = {
            x2 <- apply(x, 2, function(y) as.numeric(y > 0))
          },
          X3 = {
            x3 <- as.numeric(as.matrix(x) > 0)
            x3 <- matrix(x3, nrow = 1001)
          },
          X4 = {
            x4 <- ifelse(x > 0, 1, 0)
          },
          columns = c("test", "replications", "elapsed", 
                      "relative", "user.self"))
#   test replications elapsed relative user.self
# 1   X1          100 116.618    1.985   110.711
# 2   X2          100 105.026    1.788    94.070
# 3   X3          100  58.750    1.000    46.007
# 4   X4          100 382.410    6.509   311.567

all.equal(x1, x2, check.attributes=FALSE)
# [1] TRUE
all.equal(x1, x3, check.attributes=FALSE)
# [1] TRUE
all.equal(x1, x4, check.attributes=FALSE)
# [1] TRUE

感谢大家的讨论!

【讨论】:

  • 为什么这比ifelse 好? (不问是因为我建议过,只是好奇)
  • @ChinmayPatil -- 一方面,Ananda 的解决方案运行速度比 ifelse() 版本快 3-4 倍。 (FWIW as.logical(as.matrix(x) &gt; 0) 的速度是 他的 解决方案的两倍。)这是我用来运行几次计时赛的 data.frame:x &lt;- data.frame(replicate(1e4,sample(0:1e3)))
  • @JoshO'Brien 感谢您的回复。我也检查了同样的事情。确实是这样。 :)
  • @JoshO'Brien,谢谢。你的意思是as.numeric,对吧?我很快就会更新我的答案。
  • @ChinmayPatil,我已经用一些基准和进一步反思更新了我的答案。
【解决方案2】:

我通常使用这种方法:

df[df > 0] = 1

【讨论】:

    【解决方案3】:

    使用可以使用ifelse。它应该适用于矩阵和数据框但是,结果值将是矩阵

    > df <- cbind(aaple = c(3, 0 , 1), banana = c(0, 1, 2), orange = c(2, 1, 2))
    > df
         aaple banana orange
    [1,]     3      0      2
    [2,]     0      1      1
    [3,]     1      2      2
    
    > ifelse(df>0, 1, 0)
         aaple banana orange
    [1,]     1      0      1
    [2,]     0      1      1
    [3,]     1      1      1
    

    【讨论】:

      【解决方案4】:

      只是使用比较:

      d = t(matrix(c(3,0,2,0,1,1,1,2,2), 3))
      d > 0
      t(matrix(as.numeric(d>0), ncol(d)))
      

      【讨论】:

        【解决方案5】:
        > pippo
          person apple banana orange
        1    Tim     1      0      2
        2    Tom     0      1      1
        3    Bob     1      2      2
        > cols <- c("apple", "banana", "orange")
        > lapply(cols, function(x) {pippo[,x] <<- as.numeric(pippo[,x] >= 1)})
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-04-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-08-25
          • 2013-11-13
          • 2016-01-01
          • 2017-07-12
          相关资源
          最近更新 更多