用于将NAs更改为“无”,0或99的函数

时间:2014-07-08 15:20:07

标签: r function dataframe na

我有一个包含50列的数据集,我想编写一个函数,它可以为存在NA的50列中的每一列分配零,'无'或99(如我指定的) 。我可以为每一列编写一行代码(在我下面的示例中),但我认为必须有一种方法可以使用一个函数来减少我需要编写的代码量。

这是一个包含四列的示例。

set.seed(1)
dat <- data.frame(one = rnorm(15),
                  two = sample(LETTERS, 15),
                  three = rnorm(15),
                  four = runif(15))
dat <- data.frame(lapply(dat, function(x) { x[sample(15, 5)] <- NA; x }))
head(dat)
str(dat)
dat$two <- as.character(dat$two)

dat[["one"]][is.na(dat[["one"]])] <- 0
dat[["two"]][is.na(dat[["two"]])] <- 'none'
dat[["three"]][is.na(dat[["three"]])] <- 99
dat[["four"]][is.na(dat[["four"]])] <- 0
head(dat)

我认为起点是修改这个功能:

convert.nas <- function(obj,types){
  for (i in 1:length(obj)){
    FUN <- switch(types[i],character = as.character, 
                  numeric = as.numeric, 
                  factor = as.factor,
                  date = as.Date)
    obj[,i] <- FUN(obj[,i])
  }
  obj
}

编辑: 根据其他人的建议/意见,我将提供一些额外的背景和说明。我需要删除由于在我的脚本中稍后发生的额外数据操作(特别是下标)而导致的NA。但是,我很欣赏@Ananda关于这一点的观点,使我的数据不太可用。关于@Henrik关于选择99或0之间标准的评论,没有实际的标准&#39;从逻辑上讲,它只是特定于我需要手动定义的三列。

-al

3 个答案:

答案 0 :(得分:1)

您可以同时更改多个列:

columns_to_change <- c("one","four")
dat[columns_to_change] <- lapply(dat[columns_to_change], function(x) replace(x, is.na(x), 0))
columns_to_change <- c("two")
dat[columns_to_change] <- lapply(dat[columns_to_change], function(x) replace(x, is.na(x), "none"))
columns_to_change <- c("three")
dat[columns_to_change] <- lapply(dat[columns_to_change], function(x) replace(x, is.na(x), 99))

或没有代码重复:

L <- list(
   list(cols = c("one","four"), replacement = 0),
   list(cols = c("two"), replacement = "none"),
   list(cols = c("three"), replacement = 99)
)
for (pars in L) {
    dat[pars$cols] <- lapply(
        dat[pars$cols]
        , function(x) replace(x, is.na(x), pars$replacement)
    )
}

答案 1 :(得分:0)

您可以尝试(假设第二列是character

 dat[is.na(dat)] <- c(0,'none',99,0)[col(dat)][is.na(dat)]

@Marek是正确的,它将列转换为字符类。它可以通过

修复
 dat[] <-  lapply(dat, function(x) if(!any(grepl("[[:alpha:]]+",x))) as.numeric(x) else x)

但是,这很难看。

更新

你可以这样做:

 dat[is.na(dat)] <- list(0,'none',99,0)[col(dat)][is.na(dat)]
 dat[] <- lapply(dat, unlist)
 str(dat)
 # 'data.frame':    15 obs. of  4 variables:
 # $ one  : num  0 0.184 -0.836 0 0.33 ...
 # $ two  : chr  "M" "O" "L" "E" ...
 # $ three: num  0.8042 -0.0571 0.5036 99 99 ...
 # $ four : num  0.892 0 0.39 0 0.961 ...

答案 2 :(得分:0)

也许您正在寻找以下功能:

naSwitcher <- function(indf, cols, naType) {
  if (length(cols) != length(naType)) stop("Something's wrong")
  indf[cols] <- lapply(seq_along(indf[cols]), function(x) {
    switch(naType[x],
           "0" = { indf[cols[x]][is.na(indf[cols[x]])] <- 0; indf[cols[x]] },
           "none" = { indf[cols[x]][is.na(indf[cols[x]])] <- "none"; indf[cols[x]] },
           "99" = { indf[cols[x]][is.na(indf[cols[x]])] <- 99; indf[cols[x]] },
           "NA" = { indf[cols[x]] },
           stop("naType must be either '0', 'none', '99', or 'NA'"))    
  })
  indf
}

以下是您可以使用它的方法:

head(naSwitcher(dat, 1:4, c("0", "none", "99", "99")))
#          one  two       three       four
# 1  0.0000000    M  0.80418951  0.8921983
# 2  0.1836433    O -0.05710677 99.0000000
# 3 -0.8356286    L  0.50360797  0.3899895
# 4  0.0000000    E 99.00000000 99.0000000
# 5  0.3295078    S 99.00000000  0.9606180
# 6 -0.8204684 none -1.28459935  0.4346595

(但我建议坚持NA值...)