自动将二进制变量编码为因子?
automatically code binary variables as factors?
我有一个问题:是否有 R 函数可以自动将二进制变量编码为因子?
我有超过 80 个变量(列),其中许多是布尔性质的(0、1 和 NA),R 作为 numeric 导入。因为我想避免手动将它们转换为 因子 ,所以我想知道是否有一个函数能够自动检测 二进制数值变量 data.frame
(或 tibble
)并将它们转换为因数?我可以自己创建这样一个函数,但如果它已经存在,何必呢?
您可以使用 where
tidyselect 函数:
library(dplyr)
data %>%
mutate(across(where(~all(unique(.[!is.na(.)]) %in% c("0","1"))), as.factor))
where
的参数必须是returnsTRUE
或FALSE
的函数。这里我使用 unique
来确保所有的值都是 0
或 1
。使用 %in%
有助于处理二进制变量实际编码在字符向量中的边缘情况。由于 0L %in% "0"
、0 %in% "0"
和 "0" %in% "0"
都计算 TRUE
。
然后仅当提供给 where
的函数计算 TRUE
.
时,交叉才将 as.factor
应用于列
data %>%
dplyr::summarise(across(everything(), class))
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
#1 numeric numeric numeric numeric numeric numeric numeric numeric numeric numeric
data %>%
mutate(across(where(~all(unique(.[!is.na(.)]) %in% c("0","1"))), as.factor)) %>%
dplyr::summarise(across(everything(), class))
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
#1 factor factor factor factor factor numeric numeric numeric numeric numeric
一些示例数据:
data <- setNames(as.data.frame(cbind(replicate(5,sample(c(0,1,NA),10, replace = TRUE)),
replicate(5,runif(10,0,100)))),paste0("V",1:10))
下面我们假设一个列只要
就被认为是二进制的
- 不全是 NA 并且
- 除了 NA 之外,它仅由数字 0 和 1 值组成。
请注意,完全为 0 和 NA 或完全为 1 和 NA 的列被视为二进制,但如果这是不可取的,我们将展示如何更改代码以要求二进制列同时具有 0 和 1。
首先定义一个函数is_binary
,定义一个列是否被视为二进制。如果你想改变二进制的定义,这个函数可以改变。如果一列必须同时具有 0 和 1 才能将其视为二进制,请特别在下面的代码中将 1:2 更改为 2。如果需要,可以使用其他定义。
接下来将 is_binary
应用于每一列,返回一个逻辑向量 ok
,如果该列是二进制的,则每列一个分量为 TRUE,否则为 FALSE。
在计算答案 DF2
的行中,我们使用参数 levels = 0:1
将 factor
应用于每个二进制列,以确保仅具有 0 或仅具有 1 的列仍然具有两者级别。
没有使用包。
DF <- data.frame(a = c(0:1, NA), b = 1:3, c = NA, d = 0) # test data frame
is_binary <- function(x) {
x0 <- na.omit(x)
is.numeric(x) && length(unique(x0)) %in% 1:2 && all(x0 %in% 0:1)
}
ok <- sapply(DF, is_binary)
DF2 <- replace(DF, ok, lapply(DF[ok], factor, levels = 0:1))
str(DF2)
## 'data.frame': 3 obs. of 4 variables:
## $ a: Factor w/ 2 levels "0","1": 1 2 NA
## $ b: int 1 2 3
## $ c: logi NA NA NA
## $ d: Factor w/ 2 levels "0","1": 1 1 1
我们可以像这样将 dplyr 与 is_binary
交替使用:
DF %>% mutate(across(where(is_binary), ~ factor(., levels = 0:1)))
如果您喜欢 tidyverse,那么将 @G.Grothendieck 的 is_binary()
与 mutate_if
结合使用效果很好。
library(dplyr)
DF <- data.frame(a = c(0:1, NA), b = 1:3, c = NA, d = 0) # test data frame
is_binary <- function(x) {
x0 <- na.omit(x)
length(unique(x0)) %in% 1:2 && all(x0 %in% 0:1)
}
DF %>% mutate_if(is_binary, factor)
我有一个问题:是否有 R 函数可以自动将二进制变量编码为因子?
我有超过 80 个变量(列),其中许多是布尔性质的(0、1 和 NA),R 作为 numeric 导入。因为我想避免手动将它们转换为 因子 ,所以我想知道是否有一个函数能够自动检测 二进制数值变量 data.frame
(或 tibble
)并将它们转换为因数?我可以自己创建这样一个函数,但如果它已经存在,何必呢?
您可以使用 where
tidyselect 函数:
library(dplyr)
data %>%
mutate(across(where(~all(unique(.[!is.na(.)]) %in% c("0","1"))), as.factor))
where
的参数必须是returnsTRUE
或FALSE
的函数。这里我使用 unique
来确保所有的值都是 0
或 1
。使用 %in%
有助于处理二进制变量实际编码在字符向量中的边缘情况。由于 0L %in% "0"
、0 %in% "0"
和 "0" %in% "0"
都计算 TRUE
。
然后仅当提供给 where
的函数计算 TRUE
.
as.factor
应用于列
data %>%
dplyr::summarise(across(everything(), class))
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
#1 numeric numeric numeric numeric numeric numeric numeric numeric numeric numeric
data %>%
mutate(across(where(~all(unique(.[!is.na(.)]) %in% c("0","1"))), as.factor)) %>%
dplyr::summarise(across(everything(), class))
# V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
#1 factor factor factor factor factor numeric numeric numeric numeric numeric
一些示例数据:
data <- setNames(as.data.frame(cbind(replicate(5,sample(c(0,1,NA),10, replace = TRUE)),
replicate(5,runif(10,0,100)))),paste0("V",1:10))
下面我们假设一个列只要
就被认为是二进制的- 不全是 NA 并且
- 除了 NA 之外,它仅由数字 0 和 1 值组成。
请注意,完全为 0 和 NA 或完全为 1 和 NA 的列被视为二进制,但如果这是不可取的,我们将展示如何更改代码以要求二进制列同时具有 0 和 1。
首先定义一个函数is_binary
,定义一个列是否被视为二进制。如果你想改变二进制的定义,这个函数可以改变。如果一列必须同时具有 0 和 1 才能将其视为二进制,请特别在下面的代码中将 1:2 更改为 2。如果需要,可以使用其他定义。
接下来将 is_binary
应用于每一列,返回一个逻辑向量 ok
,如果该列是二进制的,则每列一个分量为 TRUE,否则为 FALSE。
在计算答案 DF2
的行中,我们使用参数 levels = 0:1
将 factor
应用于每个二进制列,以确保仅具有 0 或仅具有 1 的列仍然具有两者级别。
没有使用包。
DF <- data.frame(a = c(0:1, NA), b = 1:3, c = NA, d = 0) # test data frame
is_binary <- function(x) {
x0 <- na.omit(x)
is.numeric(x) && length(unique(x0)) %in% 1:2 && all(x0 %in% 0:1)
}
ok <- sapply(DF, is_binary)
DF2 <- replace(DF, ok, lapply(DF[ok], factor, levels = 0:1))
str(DF2)
## 'data.frame': 3 obs. of 4 variables:
## $ a: Factor w/ 2 levels "0","1": 1 2 NA
## $ b: int 1 2 3
## $ c: logi NA NA NA
## $ d: Factor w/ 2 levels "0","1": 1 1 1
我们可以像这样将 dplyr 与 is_binary
交替使用:
DF %>% mutate(across(where(is_binary), ~ factor(., levels = 0:1)))
如果您喜欢 tidyverse,那么将 @G.Grothendieck 的 is_binary()
与 mutate_if
结合使用效果很好。
library(dplyr)
DF <- data.frame(a = c(0:1, NA), b = 1:3, c = NA, d = 0) # test data frame
is_binary <- function(x) {
x0 <- na.omit(x)
length(unique(x0)) %in% 1:2 && all(x0 %in% 0:1)
}
DF %>% mutate_if(is_binary, factor)