将数值转换为二进制 (0/1)

2024-02-27

我有一个数据框,其中包含不同人的不同种类水果的数量。像下面这样

    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

这是你的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

Update

我不知道睡前快速发帖会产生any https://stackoverflow.com/questions/14526429/turn-a-count-matrix-into-a-binary-existence-matrix/14526637#comment20256941_14526637 讨论 https://chat.stackoverflow.com/transcript/message/7380500#7380500,但讨论本身很有趣,所以我想在这里总结一下:

我的直觉是简单地接受以下事实:TRUE and FALSE在 R 中,是数字1 and 0。如果您尝试(不太好的方法)检查​​等效性,例如1 == TRUE or 0 == FALSE, 你会得到TRUE。我的捷径(结果是采取更多时间correct, 或者至少概念上更正确方式)只是添加0 to my TRUEs and FALSEs,因为我知道 R 会将逻辑向量强制为数字。

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

阅读了评论和批评后,我想我应该添加一个选项——使用apply循环遍历列并使用as.numeric方法。那是slower比手动重新创建矩阵,但是稍微快一点比添加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

谢谢大家的讨论!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将数值转换为二进制 (0/1) 的相关文章

随机推荐