【问题标题】:Creating binary variables in R from categorical and NA variables从分类变量和 NA 变量在 R 中创建二进制变量
【发布时间】:2014-09-11 18:11:13
【问题描述】:

我有一个包含 12901 个 categorical 和 NA 观察值的数据集,包含 34 个变量。我将使用该数据集通过对消费者人口统计数据进行聚类来创建市场细分研究。

对于categorical 变量,我想转换为numeric 二进制数据。例如,变量HouseholdIncome 有六个类别:50K-75k、75k-100k、35k-50k、100k-125k、150k-175k 和 Other。我希望将HouseholdIncome 分解为六个变量 (0,0,0,0,0,1), (0,0,0,0,1,0), (0,0,0,1,0 ,0)、(0,0,1,0,0,0)、(0,1,0,0,0,0) 和 (1,0,0,0,0,0)。

问题:如何将分类值更改为二进制变量,同时保留NAs?

我的机器:

> sessionInfo()
R version 3.1.0 (2014-04-10)
Platform: x86_64-apple-darwin13.1.0 (64-bit)

我的数据:

#Head of first six rows of the first six columns
> head(Store4df)
     Age Gender HouseholdIncome MaritalStatus PresenceofChildren HomeOwnerStatus
1  55-64 Female         50k-75k        Single                 No             Own
2   <NA> Female            <NA>          <NA>               <NA>            <NA>
3   <NA>   Male            <NA>          <NA>               <NA>            <NA>
4   <NA>   Male            <NA>          <NA>               <NA>            <NA>
5    65+   Male        75k-100k        Single                 No             Own
6   <NA> Female            <NA>          <NA>               <NA>            <NA>

我已经阅读了有关该命令的其他帖子,但没有一个针对 NA 值的解决方案。我关注了一个关于Creating new dummy variable columns from categorical variables 的链接。我使用了第二个建议和二进制形式的数据,但代码不包含NA 值。

> #Use model.matrix function to 
> binary1 <- model.matrix(~ factor(Store4df$HomeMarketValue) - 1)
> #Find which rows have NA values
> which(rowSums(is.na(binary1))==ncol(binary1))
# named integer(0)
> #Get head of model.matrix of two columns with five rows
> head(binary1, n=5)
   factor(Store4df$HomeMarketValue)100k-150k factor(Store4df$HomeMarketValue)150k-200k
1                                          0                                         0
2                                          0                                         0
3                                          1                                         0
4                                          0                                         0
5                                          0                                         0

编辑:我忘了发布我有两种类型的分类变量。一个具有类别和NA 值,另一个具有TRUE 和NA 值。将具有TRUE 和NA 值的变量放入model.matrix 时出错。

> model.matrix(~ -1 + . , data = Store4df)
#Error in `contrasts<-`(`*tmp*`, value = contr.funs[1 + isOF[nn]]) : 
  contrasts can be applied only to factors with 2 or more levels

这是变量的样子:

> che <- Store4df$Pets
> summary(che)
   Mode    TRUE    NA's 
logical    3535    9628 

将一个因子变量放入model.matrix后:

> data <- model.matrix(~  Pets, data = Store4df)
> summary(data)

  (Intercept)    PetsTRUE
 Min.   :1    Min.   :1  
 1st Qu.:1    1st Qu.:1  
 Median :1    Median :1  
 Mean   :1    Mean   :1  
 3rd Qu.:1    3rd Qu.:1  
 Max.   :1    Max.   :1  

如何在第 10 列和第 12:34 列中替换 TRUE 值?

【问题讨论】:

  • 为什么需要这个?之后您打算如何处理这些数据? R 通常更喜欢分类数据保持因子形式而不是虚拟变量形式,然后根据需要应用对比。
  • @MrFlick 我将使用数据通过 CLUSTER 包中的 CLARA 函数执行聚类分析。我尝试使用 PAM,但无法预先创建数据集部分填充率的差异度量 b/c。我正在切换到一个数值算法,该算法采用样本而不是计算与每个观察值的距离。

标签: r binary


【解决方案1】:

我不认为model.matrix 可以使用参数来详细说明如何处理缺失数据但是,您可以将默认选项更改为na.pass,从而在model.matrix 调用中保留缺失值。

# create data with missing values
set.seed(1)
dat <- data.frame(x=sample(letters[1:3],20,TRUE), y=rnorm(20), 
                                                  stringsAsFactors=FALSE)
dat[c(5,10,15),1] <- NA

# set default options for handling missing data
options(na.action='na.pass')

# note that rows with missing data are retained
m <- model.matrix(~ -1 + x + y, data=dat)

# return option to default
options(na.action='na.omit')

来自here

【讨论】:

  • 那是因为x 没有在Storedf 中定义。对于您的实际数据,请尝试Store4df.m &lt;- model.matrix(~ -1 + HomeMarketValue, data = Store4df)
  • 好东西。是的,您可以添加多个变量,例如,model.matrix(~ -1 + HouseholdIncome + HomeMarketValue, data = Store4df)。如果你想包含所有变量,你实际上可以只做model.matrix(~ -1 + . , data = Store4df)。也不知道你想如何处理参考水平,但如果你想在虚拟矩阵中包含每个变量的所有水平,那么this question will help
  • 您可以只添加零,因为TRUE 被视为1。试试c(TRUE, FALSE, NA) + 0 或c(TRUE, FALSE, NA) * 1
  • 斯科特,对不起,我不太听从上面的评论。但是关于您问题中的编辑:我不认为是 pets 变量导致了问题。即尝试model.matrix(~ Pets, data=Store4df) - 应该可以正常运行。
  • 该错误看起来好像来自您的变量之一是恒定的/只有一个级别。试试这个例子:dat &lt;- data.frame(x=sample(letters[1:3],10,TRUE),z=factor("oneLevel"), stringsAsFactors=FALSE) 然后model.matrix(~ -1 + x + z, data=dat) - 这会重现您编辑中的错误,因为z 只有一个级别。
【解决方案2】:

对于解决方法,我要做的是将&lt;NA&gt; 替换为“不可用”(或其他内容)。然后,&lt;NA&gt; 也将被视为因子水平。

copy <-Store4df
levels(copy$HomeMarketValue) <- c(levels(copy$HomeMarketValue),"Not Available")
copy$HomeMarketValue[is.na(copy$HomeMarketValue)]<-"Not Available"
binary1 <- model.matrix(~ factor(copy$HomeMarketValue) - 1)

请注意,我没有测试上述内容,因为您没有提供我可以用来重现您的示例的数据。但是,现在您应该得到一个因子级别的虚拟变量,即“不可用”为 1。

举例:

A<-data.frame(ID=1:100,x=sample(c(1:5,NA),100,replace=TRUE))
A$x[is.na(A$x)]<-"NotAvailable"
MM<-model.matrix(~factor(A$x)-1)
for(i in 1:5) {
  MM[,i][MM[,6]==1]<-NA
}
MM<-MM[,-6]
head(MM)
##  factor(A$x)1 factor(A$x)2 factor(A$x)3 factor(A$x)4 factor(A$x)5
##1            0            0            1            0            0
##2            1            0            0            0            0
##3           NA           NA           NA           NA           NA
##4            1            0            0            0            0
##5            0            0            0            1            0
##6            0            0            0            1            0

【讨论】:

  • @mrgriebe 我在解决方案的第二行收到一条错误消息警告消息:在[&lt;-.factor(*tmp*, is.na(copy$HomeMarketValue), value = c(9L, :无效因子水平,NA 生成
  • 使用'levels'添加因子水平“NotAvailable”。
  • @mrgriebe 回顾解决方案,我认为将 NA 设为变量不是一个好主意。我认为所有分类观察都应该有自己的列,但保留 NA 值。我们怎么能做到这一点?我将使用数据集进行聚类,CLARA 将计算从一个缺失的反对到另一个的距离。创建样本后,CLARA 将为中心点分配一个 NA 值。我编辑了我的帖子以展示数据集的使用。
  • 就像我说的,它可以解决。我认为它仍然可以回答您的问题。
  • 你是对的,我们仍然在数据集中有 NA 值。但是,我正在计算距离,只要每对观察结果至少缺少一个案例,就可以了。我还没有看到任何数据挖掘者将 NA 转换为二进制变量。在某些情况下,将 NA 设为因子水平可能有用,但我们需要在每个因子中使用 NA。
【解决方案3】:

使用caret 包很容易做到这一点。
下面的代码是一次完成任意数量变量的快速方法。

require(caret)
# Make sure variables you are using are factors

VARS.TO.MAKE.DUMMY <-  #list of variables to convert to dummy
    c("HouseholdIncome", "Age")

dat.temp <- # Temporary data.frame to make dummies
    Store4df[,VARS.TO.MAKE.DUMMY]

dummy.vars <- # create dummies  
    predict(  
        dummyVars(  
            ~ .,   
            data = dat.temp
            ),
        newdata = dat.temp,
        na.action = na.pass
        )

Store4df <- # Append results to original dataframe
    cbind(Store4df, as.data.frame(dummy.vars))

rm(dummy.vars, dat.temp) # Garbage collection

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 2018-07-18
    • 2019-06-28
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 2015-08-17
    • 2018-03-17
    相关资源
    最近更新 更多