用分类数据集R中的模式替换NA



我有一个数据集,包含10个变量的categoricalNA观测值。我想用模式替换每列的NA值。我为每个变量做了一个直方图,以确定每个观察的密度,并得到了模式。我知道用什么值来替换每列中的NA

我看到有一个相关的帖子,但我已经知道该取代什么价值观了。链接如下:替换R 中缺失值的平均值或模式

以下是重现数据集:

> #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

这里有一个例子:

> #The head of the first five observations
> head(SmallStoredf, n=5)
    Age Gender HouseholdIncome MaritalStatus PresenceofChildren HomeOwnerStatus HomeMarketValue
1  <NA>   Male            <NA>          <NA>               <NA>            <NA>            <NA>
2 45-54 Female            <NA>          <NA>               <NA>            <NA>            <NA>
5 45-54 Female        75k-100k       Married                Yes             Own       150k-200k
6 25-34   Male        75k-100k       Married                 No             Own       300k-350k
7 35-44 Female       125k-150k       Married                Yes             Own       250k-300k
  Occupation             Education LengthofResidence
1       <NA>                  <NA>              <NA>
2       <NA>                  <NA>              <NA>
5       <NA> Completed High School           9 Years
6       <NA> Completed High School       11-15 years
7       <NA> Completed High School           2 Years  

在本例中,我希望HomeOwnerStatus中的NA s被Own替换,HomeMarketValue350K-500K替换,并且OccupationProfessional替换。

编辑:我尝试在中输入值,但在其中三列中出现错误。

> replacementVals <- c(Age = "45-54", Gender = "Male", HouseholdIncome = "50K-75K", 
+                      MaritalStatus = "Single", PresenceofChildren = "No",
+                      HomeOwnerStatus = "Own", HomeMarketValue = "350K-500K",
+                      Occupation = "Professional", Education = "Completed High School",
+                      LengthofResidence = "11-15yrs")
> indx1 <- replacementVals[col(df2)][is.na(df2[,names(replacementVals)])]
> df2[is.na(df2[,names(replacementVals)])]  <- indx1
#Warning messages:
#1: In `[<-.factor`(`*tmp*`, thisvar, value = c("50K-75K", "50K-75K",  :
  invalid factor level, NA generated
#2: In `[<-.factor`(`*tmp*`, thisvar, value = c("350K-500K", "350K-500K",  :
  invalid factor level, NA generated
#3: In `[<-.factor`(`*tmp*`, thisvar, value = c("11-15yrs", "11-15yrs",  :
  invalid factor level, NA generated

这是输出:

> head(SmallStoredf)
    Age Gender HouseholdIncome MaritalStatus PresenceofChildren HomeOwnerStatus HomeMarketValue
1 45-54   Male            <NA>        Single                 No             Own            <NA>
2 45-54 Female            <NA>        Single                 No             Own            <NA>
5 45-54 Female        75k-100k       Married                Yes             Own       150k-200k
6 25-34   Male        75k-100k       Married                 No             Own       300k-350k
7 35-44 Female       125k-150k       Married                Yes             Own       250k-300k
8 55-64   Male        75k-100k       Married                 No             Own       150k-200k
    Occupation             Education LengthofResidence
1 Professional Completed High School              <NA>
2 Professional Completed High School              <NA>
5 Professional Completed High School           9 Years
6 Professional Completed High School       11-15 years
7 Professional Completed High School           2 Years
8 Professional Completed High School       16-19 years

仅替换了某些列中的NA值。

我稍微修改了一下您的可复制示例,下面是的设置

> #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
> dat[6,1]<-NA
#output
#     x                        y
#1     a  1.511781168450847978590
#2     b  0.389843236411431093291
#3     b -0.621240580541803755210
#4     c -2.214699887177499881830
#5  <NA>  1.124930918143108193874
#6     c                       NA
#7     c -0.016190263098946087311
#8     b  0.943836210685299215051
#9     b  0.821221195098088552200
#10 <NA>  0.593901321217508826322
#11    a  0.918977371608218240873
#12    a  0.782136300731067102276
#13    c  0.074564983365190601328
#14    b -1.989351695863372793127
#15 <NA>  0.619825747894710232799
#16    b -0.056128739529000784558
#17    c -0.155795506705329295238
#18    c -1.470752383899274429169
#19    b -0.478150055108620353206
#20    c  0.417941560199702411005

现在定义你的替换vals,用你想让NA替换的列来标记

replacementVals<-c(x="Xreplace", y="Yreplace")

下一个呼叫可以在一次中替换它们

dat[is.na(dat[,names(replacementVals)])]<-replacementVals
#          x                   y
#1         a    1.51178116845085
#2         b   0.389843236411431
#3         b  -0.621240580541804
#4         c    -2.2146998871775
#5  Xreplace    1.12493091814311
#6         c            Yreplace
#7         c -0.0161902630989461
#8         b   0.943836210685299
#9         b   0.821221195098089
#10 Yreplace   0.593901321217509
#11        a   0.918977371608218
#12        a   0.782136300731067
#13        c  0.0745649833651906
#14        b   -1.98935169586337
#15 Xreplace    0.61982574789471
#16        b -0.0561287395290008
#17        c  -0.155795506705329
#18        c   -1.47075238389927
#19        b   -0.47815005510862
#20        c   0.417941560199702

但正如akrun所指出的,并随后得到了解决,这并不能很好地映射到您的第二个数据帧示例。这只是直接从他们的评论中得出的(所以无论哪种方式,他们都可能会得到这个问题的检查)

我们将进行设置,除了结果外,我不会进行所有打印

HomeOwnerStatus = c(NA,NA,NA ,"Rent", "Rent" ) 
HomeMarketValue = c(NA,NA,NA, "350k", "350k") 
Occupation = c(NA,NA,NA, NA, NA) 
SmallStoreddf<-data.frame(HomeOwnerStatus,HomeMarketValue,Occupation, stringsAsFactors=FALSE)
replacementVals<-c("HomeOwnerStatus" = "Rent", "HomeMarketValue"="350k", "Occupation"="Professional")

然后分两步(可以组合成一条很长的线),你就可以进行

#get the values that we will be replacing
indx1<-replacementVals[col(SmallStoreddf)][is.na(SmallStoreddf[, names(replacementVals)])]
#do the replacement
SmallStoreddf[is.na(SmallStoredf[,names(replacementVals)])] <-indx1
#  HomeOwnerStatus HomeMarketValue   Occupation
#1             Own            350k Professional
#2             Own            350k Professional
#3             Own            350k Professional
#4            Rent            350k Professional
#5            Rent            350k Professional

尝试:(使用第二个示例,因为当您显示两个数据集时有点不清楚)

indx <- which(is.na(SmallStoredf), arr.ind=TRUE)
SmallStoredf[indx] <- c("Own", "350K-500K", "Professional")[indx[,2]]
SmallStoredf
#  HomeOwnerStatus HomeMarketValue   Occupation
#1             Own       350K-500K Professional
#2             Own       350K-500K Professional
#3             Own       350K-500K Professional
#4            Rent       350k-500k Professional
#5            Rent        500k-1mm Professional

升级注释。

如果要用最频繁的类别替换丢失的数据,则变量中的类别数可能相等。因此,在下面的代码中,替换是从最频繁的类别中随机采样的。

# some example data with missing
set.seed(1)
dat <- data.frame(x=sample(letters[1:3],20,TRUE), 
                  y=sample(letters[1:3],20,TRUE),
                  w=rnorm(20),
                  z=sample(letters[1:3],20,TRUE),                  
                  stringsAsFactors=FALSE)
dat[c(5,10,15),1] <- NA
dat[c(3,7),2] <- NA
# function to get replacement for missing
# sample is used to randomly select categories, allowing for the case 
# when the maximum frequency is shared by more than one category 
f <- function(x) {
                tab <- table(x)
                l <- sum(is.na(x))
                sample(names(tab)[tab==max(tab)], l, TRUE)
                }
# as we are using sample, set.seed before replacing
set.seed(1)
for(i in 1:ncol(dat)){
            if(!is.numeric(dat[i]))
                  dat[i][is.na(dat[i])] <- f(dat[i])
            }

温和警告:在以这种方式输入缺失数据之前,您应该仔细考虑。例如,最高和最低类别的收入往往更可能缺失。用这种方法计算平均工资可能有误。你应该考虑为什么每个变量都缺失,以及假设数据是MCAR或MAR是否合理。如果是,我会考虑一种更稳健的插补方法(mice包)。

最新更新