簡體   English   中英

在 R 中將因子轉換為二進制

[英]Converting factors to binary in R

我正在嘗試將因子變量轉換為二進制/布爾值(0 或 1)。

樣本數據:

df  <-data.frame(a = c(1,2,3), b = c(1,1,2), c = c("Rose","Pink","Red"), d = c(2,3,4))

嘗試像這樣轉換它:a,b,IsRose,IsPink,IsRed,d

實際與預期結果

為此,我嘗試了以下方法但收效甚微。

library(ade4)
acm.disjonctif(df)

在基礎 R 中,您可以在級別上使用sapply() ,使用==檢查是否存在,並使用as.integer()將其強制為二進制。

cbind(df[1:2], sapply(levels(df$c), function(x) as.integer(x == df$c)), df[4])
#   a b Pink Red Rose d
# 1 1 1    0   0    1 2
# 2 2 1    1   0    0 3
# 3 3 2    0   1    0 4

但是由於您有一百萬行,您可能想要使用data.table

library(data.table)
setDT(df)[, c(levels(df$c), "c") := 
    c(lapply(levels(c), function(x) as.integer(x == c)), .(NULL))]

這使

df
#    a b d Pink Red Rose
# 1: 1 1 2    0   0    1
# 2: 2 1 3    1   0    0
# 3: 3 2 4    0   1    0

如果需要,您可以使用setcolorder(df, c(1, 2, 4:6, 3))重置列順序。

你可以通過重塑來做到這一點:

library(dplyr)
library(tidyr)

df %>%
  mutate(value = 1,
         c = paste0("Is", c)) %>%
  spread(c, value, fill = 0)

使用 dplyr 並將其放在管道上。 @bramtayl 的回答更簡潔,但我找不到使用自定義變量名稱的方法。 這不太干凈,但更干燥

expand_factor <- function(df,variable){
    variable = as.name(variable)
    paste0('~ ',variable,' -1',collapse = '') %>% 
        as.formula ->formulae

    current.na.action <- options('na.action')
    options(na.action='na.pass')
    expanded<-model.matrix(data=df,object = formulae)
    options(na.action=current.na.action)

    colnames(expanded) <-gsub(replacement = 'is_',x = colnames(expanded),pattern=variable) 

    expanded %>% 
        tbl_df %>% 
        mutate_each(funs(as.integer)) ->expanded

    return(bind_cols(df,expanded))
}

library(dplyr)
df  <-data_frame(x = iris$Species,y = iris$Petal.Width)
df <- rbind(data_frame(x=NA,y = NA),df)

df %>% 
    expand_factor('x')

> df %>% 
+   expand_factor('x')
# A tibble: 151 <U+00D7> 5
        x     y is_setosa is_versicolor is_virginica
    <chr> <dbl>     <int>         <int>        <int>
1    <NA>    NA        NA            NA           NA
2  setosa   0.2         1             0            0
3  setosa   0.2         1             0            0
4  setosa   0.2         1             0            0
5  setosa   0.2         1             0            0
6  setosa   0.2         1             0            0
7  setosa   0.4         1             0            0
8  setosa   0.3         1             0            0
9  setosa   0.2         1             0            0
10 setosa   0.2         1             0            0
# ... with 141 more rows
dummy <- function(df) {  
  NUM <- function(dataframe)dataframe[,sapply(dataframe,is.numeric)]
  FAC <- function(dataframe)dataframe[,sapply(dataframe,is.factor)]

  require(ade4)
  if (is.null(ncol(NUM(df)))) {
      DF <- data.frame(NUM(df), acm.disjonctif(FAC(df)))
      names(DF)[1] <- colnames(df)[which(sapply(df, is.numeric))]
  } else {
      DF <- data.frame(NUM(df), acm.disjonctif(FAC(df)))
  }
  return(DF)
} 

為了完整起見,在此解決方案 ( https://stackoverflow.com/a/33990970/2725773 ) 的基礎上,這里有最新的 tidyverse 軟件包的更新。

library(tidyverse)

df %>%
  mutate(value = 1,
         c = paste0("Is", c)) %>%
  pivot_wider(names_from  = c,
              values_from = value,
              values_fill = 0)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM