将逻辑值(TRUE / FALSE)替换为数值(1 / 0)。

40

我正在使用以下命令从R中导出数据:

write.table(output,file = "data.raw", na "-9999", sep = "\t", row.names = FALSE, col.names = FALSE)

我的数据输出正确,但它将所有逻辑变量导出为TRUEFALSE

我需要在另一个只能处理数值的程序中读取数据。在导出期间是否有一种有效的方法可以将logical列转换为数字1和0?由于我有大量的数字变量,所以希望能够自动遍历数据表中的所有变量。

或者,如果我的输出对象是data.table,是否有一种将data.table中所有逻辑变量转换为数值变量的有效方法?

如果有帮助的话,以下是生成包含逻辑变量的data.table的代码(其中并不是大量逻辑变量,但足以用作示例代码):

DT = data.table(cbind(1:100, rnorm(100) > 0)
DT[ , V3:= V2 == 1 ]
DT[ , V4:= V2 != 1 ]

5
你问了关于效率的问题,因此:as.integer的速度可能比as.numeric快3倍(以下所有回答都使用它)。我尝试了:x <- sample(c(TRUE,FALSE,NA),1e8,replace=TRUE); system.time("+"(x)); system.time(as.integer(x)); system.time(as.numeric(x)) - Frank
4
谢谢,我想知道为什么每个人都在使用 as.numeric-- 我以为由于存储要求更小,as.integer 会更快 ... - MichaelChirico
2
@MichaelChirico 你说的 as.integer 是对的。使用 data.table,如果你想用 mean 或其他方法改变该列中的某些值,就会出现“class”冲突。否则,使用 value=dat[[j]]+0L) 会更容易。 - akrun
最短的是 +A - U13-Forward
7个回答

35

最简单的方法!

将您的矩阵乘以1

例如:

A <- matrix(c(TRUE,FALSE,TRUE,TRUE,TRUE,FALSE,FALSE,TRUE),ncol=4)
A

#       [,1] [,2]  [,3]  [,4]
# [1,]  TRUE TRUE  TRUE FALSE
# [2,] FALSE TRUE FALSE  TRUE

B <- 1*A
B
#      [,1] [,2] [,3] [,4]
# [1,]    1    1    1    0
# [2,]    0    1    0    1

(您还可以添加零:B <- 0 + A


3
不仅是最简单的,而且也是最快的。 - krassowski

33

对于一个data.frame,您可以使用以下方法将所有逻辑列转换为数字:

# The data
set.seed(144)
dat <- data.frame(V1=1:100,V2=rnorm(100)>0)
dat$V3 <- dat$V2 == 1
head(dat)
#   V1    V2    V3
# 1  1 FALSE FALSE
# 2  2  TRUE  TRUE
# 3  3 FALSE FALSE
# 4  4 FALSE FALSE
# 5  5 FALSE FALSE
# 6  6  TRUE  TRUE

# Convert all to numeric
cols <- sapply(dat, is.logical)
dat[,cols] <- lapply(dat[,cols], as.numeric)
head(dat)
#   V1 V2 V3
# 1  1  0  0
# 2  2  1  1
# 3  3  0  0
# 4  4  0  0
# 5  5  0  0
# 6  6  1  1

data.table 语法中:

# Data
set.seed(144)
DT = data.table(cbind(1:100,rnorm(100)>0))
DT[,V3 := V2 == 1]
DT[,V4 := FALSE]
head(DT)
#    V1 V2    V3    V4
# 1:  1  0 FALSE FALSE
# 2:  2  1  TRUE FALSE
# 3:  3  0 FALSE FALSE
# 4:  4  0 FALSE FALSE
# 5:  5  0 FALSE FALSE
# 6:  6  1  TRUE FALSE

# Converting
(to.replace <- names(which(sapply(DT, is.logical))))
# [1] "V3" "V4"
for (var in to.replace) DT[, (var):= as.numeric(get(var))]
head(DT)
#    V1 V2 V3 V4
# 1:  1  0  0  0
# 2:  2  1  1  0
# 3:  3  0  0  0
# 4:  4  0  0  0
# 5:  5  0  0  0
# 6:  6  1  1  0

11

只是一个“a”怎么样呢:

dat <- data.frame(le = letters[1:10], lo = rep(c(TRUE, FALSE), 5))
dat
   le    lo
1   a  TRUE
2   b FALSE
3   c  TRUE
4   d FALSE
5   e  TRUE
6   f FALSE
7   g  TRUE
8   h FALSE
9   i  TRUE
10  j FALSE
dat$lo <- as.numeric(dat$lo)
dat
   le lo
1   a  1
2   b  0
3   c  1
4   d  0
5   e  1
6   f  0
7   g  1
8   h  0
9   i  1
10  j  0

或者另一种方法是使用dplyr,以便在某些情况下(谁也不知道)你的数据将被导入到R中时保留先前的列。

library(dplyr)
dat <- dat %>% mutate(lon = as.numeric(lo))
dat
Source: local data frame [10 x 3]

   le    lo lon
1   a  TRUE   1
2   b FALSE   0
3   c  TRUE   1
4   d FALSE   0
5   e  TRUE   1
6   f FALSE   0
7   g  TRUE   1
8   h FALSE   0
9   i  TRUE   1
10  j FALSE   0

编辑:循环

我不知道这里的代码是否有效,但它会检查所有列并将逻辑值转换为数字。当然,如果你的TRUEFALSE不是逻辑值而是字符串(这可能是偏远的情况),我的代码就不起作用了。

for(i in 1:ncol(dat)){

    if(is.logical(dat[, i]) == TRUE) dat[, i] <- as.numeric(dat[, i]) 

    }

11

如果有多个列,则可以使用set(使用@josilber的示例)

library(data.table)
Cols <-  which(sapply(dat, is.logical))
setDT(dat)

for(j in Cols){
 set(dat, i=NULL, j=j, value= as.numeric(dat[[j]]))
}

10

正如Ted Harding在R-help邮件列表中指出的那样,将逻辑对象转换为数字的一种简单方法是对它们执行算术运算。方便的方法是使用* 1+ 0,这将保持TRUE/FALSE == 1/0范式。

对于您的模拟数据(我已经更改了代码以使用普通的R包并减少大小):

df    <- data.frame(cbind(1:10, rnorm(10) > 0))
df$X3 <- df$X2 == 1
df$X4 <- df$X2 != 1

您获得的数据集包含数字和布尔变量的混合:

   X1 X2    X3    X4
1   1  0 FALSE  TRUE
2   2  0 FALSE  TRUE
3   3  1  TRUE FALSE
4   4  1  TRUE FALSE
5   5  1  TRUE FALSE
6   6  0 FALSE  TRUE
7   7  0 FALSE  TRUE
8   8  1  TRUE FALSE
9   9  0 FALSE  TRUE
10 10  1  TRUE FALSE

Now let

df2 <- 1 * df

如果您的数据集包含字符或因子变量,您需要对df的一个子集应用此操作,过滤掉这些变量。

df2等于

   X1 X2 X3 X4
1   1  0  0  1
2   2  0  0  1
3   3  1  1  0
4   4  1  1  0
5   5  1  1  0
6   6  0  0  1
7   7  0  0  1
8   8  1  1  0
9   9  0  0  1
10 10  1  1  0

这个值是100%数字的,使用str(df2)查看。

现在,您可以安全地将df2导出到其他程序中。


6

一行解决方案

使用以下代码,我们将所有逻辑列转换为数值列。

library(magrittr)
dat %<>% mutate_if(is.logical,as.numeric) 

3
也可以使用mutate(across(where(is.logical), as.numeric))来将所有逻辑变量转换为数值类型。 - user66081

3

与@saebod相同,但使用通常的管道。

library(dplyr)  

dat <- dat %>% 
  mutate_if(is.logical, as.numeric)  

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接