web-dev-qa-db-ja.com

空のセルを「NA」に変更します

これが私のデータの link です。

私の目標は、カテゴリ値または数値に関係なく、すべての空白セルに「NA」を割り当てることです。私はna.strings = ""を使用しています。ただし、すべての空白セルにNAを割り当てるわけではありません。

## reading the data
dat <- read.csv("data2.csv")
head(dat)
  mon hr        acc   alc sex spd axles door  reg                                 cond1 drug1
1   8 21 No Control  TRUE   F   0     2    2      Physical Impairment (Eyes, Ear, Limb)     A
2   7 20 No Control FALSE   M 900     2    2                                Inattentive     D
3   3  9 No Control FALSE   F 100     2    2 2004                                Normal     D
4   1 15 No Control FALSE   M   0     2    2      Physical Impairment (Eyes, Ear, Limb)     D
5   4 21 No Control FALSE      25    NA   NA                                                D
6   4 20 No Control    NA   F  30     2    4                Drinking Alcohol - Impaired     D
       inj1 PED_STATE st rac1
1     Fatal      <NA>  F <NA>
2  Moderate      <NA>  F <NA>
3  Moderate      <NA>  M <NA>
4 Complaint      <NA>  M <NA>
5 Complaint      <NA>  F <NA>
6  Moderate      <NA>  M <NA>


## using na.strings
dat2 <- read.csv("data2.csv", header=T, na.strings="")
head(dat2)
  mon hr        acc   alc sex spd axles door  reg                                 cond1 drug1
1   8 21 No Control  TRUE   F   0     2    2 <NA> Physical Impairment (Eyes, Ear, Limb)     A
2   7 20 No Control FALSE   M 900     2    2 <NA>                           Inattentive     D
3   3  9 No Control FALSE   F 100     2    2 2004                                Normal     D
4   1 15 No Control FALSE   M   0     2    2 <NA> Physical Impairment (Eyes, Ear, Limb)     D
5   4 21 No Control FALSE      25    NA   NA <NA>                                  <NA>     D
6   4 20 No Control    NA   F  30     2    4 <NA>           Drinking Alcohol - Impaired     D
       inj1 PED_STATE st rac1
1     Fatal        NA  F   NA
2  Moderate        NA  F   NA
3  Moderate        NA  M   NA
4 Complaint        NA  M   NA
5 Complaint        NA  F   NA
6  Moderate        NA  M   NA
56
S Das

行5列の「性別」について話していると思います。 data2.csvファイルでは、セルにスペースが含まれているため、Rによって空と見なされない場合があります。

また、行5の列「axles」と「door」では、data2.csvから読み取られた元の値が文字列「NA」であることに気付きました。おそらくna.stringsとしても扱いたいでしょう。これをする、

dat2 <- read.csv("data2.csv", header=T, na.strings=c("","NA"))

編集:

Data2.csvをダウンロードしました。はい、行5列の「性別」にスペースがあります。あなたが望んでいるのは

na.strings=c(""," ","NA")
82
Badoe

Gsubを使用して、 ""やスペースなどの空の複数の突然変異をNAに置き換えることができます。

data= data.frame(cats=c('', ' ', 'meow'), dogs=c("woof", " ", NA))
apply(data, 2, function(x) gsub("^$|^ $", NA, x))
29
sclarky

dplyrを使用したより目に優しいソリューションは

require(dplyr)

## fake blank cells
iris[1,1]=""

## define a helper function
empty_as_na <- function(x){
    if("factor" %in% class(x)) x <- as.character(x) ## since ifelse wont work with factors
    ifelse(as.character(x)!="", x, NA)
}

## transform all columns
iris %>% mutate_each(funs(empty_as_na)) 

列のサブセットのみに修正を適用するには、dplyrの列一致構文を使用して、目的の列を指定できます。例:mutate_each(funs(empty_as_na), matches("Width"), Species)

テーブルに日付が含まれている場合は、ifelseよりタイプセーフな バージョンの使用を検討する必要があります

18
Holger Brandl

私は最近、同様の問題に遭遇しました。これが私にとってはうまくいきました。変数が数値の場合、単純なdf$Var[df$Var == ""] <- "NA"で十分です。しかし、変数が因子である場合、最初にそれを文字に変換してから、""セルを目的の値に置き換えてから、因子に戻す必要があります。したがって、適切な場合、Sex変数は、それが要因になると思います。空のセルを置き換える場合は、次のようにします。

df$Var <- as.character(df$Var)
df$Var[df$Var==""] <- "NA"
df$Var <- as.factor(df$Var)
8
ZKH

これはトリックを行う必要があります

dat <- dat %>% mutate_all(na_if,"")
4
Jonathan

私の機能は、ヘイブンまたは外部パッケージを使用して外部ファイルを読み取る場合、要因、文字ベクトル、および潜在的な属性を考慮します。また、異なる自己定義na.stringsのマッチングも可能です。すべての列を変換するには、単にlappyを使用します:df[] = lapply(df, blank2na, na.strings=c('','NA','na','N/A','n/a','NaN','nan'))

コメントをもっと見る:

#' Replaces blank-ish elements of a factor or character vector to NA
#' @description Replaces blank-ish elements of a factor or character vector to NA
#' @param x a vector of factor or character or any type
#' @param na.strings case sensitive strings that will be coverted to NA. The function will do a trimws(x,'both') before conversion. If NULL, do only trimws, no conversion to NA.
#' @return Returns a vector trimws (always for factor, character) and NA converted (if matching na.strings). Attributes will also be kept ('label','labels', 'value.labels').
#' @seealso \code{\link{ez.nan2na}}
#' @export
blank2na = function(x,na.strings=c('','.','NA','na','N/A','n/a','NaN','nan')) {
    if (is.factor(x)) {
        lab = attr(x, 'label', exact = T)
        labs1 <- attr(x, 'labels', exact = T)
        labs2 <- attr(x, 'value.labels', exact = T)

        # trimws will convert factor to character
        x = trimws(x,'both')
        if (! is.null(lab)) lab = trimws(lab,'both')
        if (! is.null(labs1)) labs1 = trimws(labs1,'both')
        if (! is.null(labs2)) labs2 = trimws(labs2,'both')

        if (!is.null(na.strings)) {
            # convert to NA
            x[x %in% na.strings] = NA
            # also remember to remove na.strings from value labels 
            labs1 = labs1[! labs1 %in% na.strings]
            labs2 = labs2[! labs2 %in% na.strings]
        }

        # the levels will be reset here
        x = factor(x)

        if (! is.null(lab)) attr(x, 'label') <- lab
        if (! is.null(labs1)) attr(x, 'labels') <- labs1
        if (! is.null(labs2)) attr(x, 'value.labels') <- labs2
    } else if (is.character(x)) {
        lab = attr(x, 'label', exact = T)
        labs1 <- attr(x, 'labels', exact = T)
        labs2 <- attr(x, 'value.labels', exact = T)

        # trimws will convert factor to character
        x = trimws(x,'both')
        if (! is.null(lab)) lab = trimws(lab,'both')
        if (! is.null(labs1)) labs1 = trimws(labs1,'both')
        if (! is.null(labs2)) labs2 = trimws(labs2,'both')

        if (!is.null(na.strings)) {
            # convert to NA
            x[x %in% na.strings] = NA
            # also remember to remove na.strings from value labels 
            labs1 = labs1[! labs1 %in% na.strings]
            labs2 = labs2[! labs2 %in% na.strings]
        }

        if (! is.null(lab)) attr(x, 'label') <- lab
        if (! is.null(labs1)) attr(x, 'labels') <- labs1
        if (! is.null(labs2)) attr(x, 'value.labels') <- labs2
    } else {
        x = x
    }
    return(x)
}
3
Jerry T

dplyrmutate_atを使用することもできます

dat <- dat %>%
mutate_at(vars(colnames(.)),
        .funs = funs(ifelse(.=="", NA, as.character(.))))

変更する個々の列を選択します。

dat <- dat %>%
mutate_at(vars(colnames(.)[names(.) %in% c("Age","Gender")]),
        .funs = funs(ifelse(.=="", NA, as.character(.))))

スキップする個々の列を選択します。

dat <- dat %>%
mutate_at(vars(colnames(.)[!names(.) %in% c("Birthday")]),
        .funs = funs(ifelse(.=="", NA, as.character(.))))
1
camnesia

上記の多くのオプションは適切に機能しますが、ターゲット以外の変数をchrに強制することには問題があることがわかりました。 ifelse内でgreplおよびlapplyを使用すると、この限定された効果が解決されます(限定的なテストで)。 greplでのslarkyの正規表現の使用:

set.seed(42)
x1 <- sample(c("a","b"," ", "a a", NA), 10, TRUE)
x2 <- sample(c(rnorm(length(x1),0, 1), NA), length(x1), TRUE)

df <- data.frame(x1, x2, stringsAsFactors = FALSE)

文字クラスへの強制の問題:

df2 <- lapply(df, function(x) gsub("^$|^ $", NA, x))
lapply(df2, class)

$ x1 [1]「キャラクター」

$ x2 [1]「キャラクター」

Ifelseを使用した解決:

df3 <- lapply(df, function(x) ifelse(grepl("^$|^ $", x)==TRUE, NA, x))
lapply(df3, class)

$ x1 [1]「キャラクター」

$ x2 [1]「数値」

1
Todd D

使っていただけませんか

dat <- read.csv("data2.csv",na.strings=" ",header=TRUE)

データを読み込むときにすべての空白をNAに変換する必要があります。引用符の間にスペースを入れてください

0
user8333183