빈 셀을 "NA"로 변경


80

여기 내 데이터 링크 가 있습니다.

내 목표는 범주 또는 숫자 값에 관계없이 모든 빈 셀에 "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

표 및 ERD를 포함하여 텍스트에는 이미지 / 링크가 아닌 텍스트를 사용 하십시오 . 다른 텍스트에서 의역 또는 인용. 텍스트로 표현할 수 없거나 텍스트를 보강하기 위해 이미지를 사용하십시오. 이미지를 검색하거나 잘라내어 붙여 넣을 수 없습니다. 이미지와 함께 범례 / 키 및 설명을 포함합니다. 게시물을 독립적으로 만드십시오. 편집 기능을 사용하여 이미지 / 링크를 삽입합니다.
philipxy

답변:


98

나는 당신이 행 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 행 "sex"열에 공백이 있습니다. 그래서 당신은

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

34

gsub를 사용하여 ""또는 공백과 같이 비어있는 여러 변형을 NA로 바꿀 수 있습니다.

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

2
gsub("^$", NA, trimws(x))셀 내에서 둘 이상의 공간을 처리 하는 데 사용할 수도 있습니다 . 그러나 이러한 접근 방식은 모든 열을 문자열 / 문자 변수로 변환합니다 (아직 그렇지 않은 경우).
JWilliman

27

보다 눈 친화적 인 솔루션 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


11
어떻게 새 라이브러리를 추가하고 새 함수를 만드는 것이 에 더 친숙 합니까? 그리고 나는 당신이 필요하다고 생각합니다 ifelse(x %in% c(""," ","NA"), NA, x).
zx8754

4
와 함께 함수를 사용 mutate_each하면 더 많은 유연성과 재사용 가능한 패턴이 제공됩니다. dplyr요즘 R- 워크 플로에서 어디에나 존재하며 대답을 독립적으로 만들기 위해 추가되었습니다. x!=""""도 "NA"도 비어 있지 않기 때문에 여기에서 옳다고 생각 합니다. 또한 @sclarky의 대답은 숫자를 포함하는 데이터 프레임에 대해 실패하고 @Badoe는 기존 data.frame에 대한 문제를 실제로 해결하지 않으므로 다른 대답은 아직 일반적인 방식으로 질문에 대답하지 않는 것 같습니다. 더 나은 솔루션에 대해 알게되어 기쁩니다.
Holger Brandl 2016 년

1
dplyr은 오늘날 R- 워크 플로에서 어디에나 존재 합니다. 그리고 " 및 @ Badoe 's가 기존 data.frames의 문제를 실제로 해결하지 못함 "은 무엇을 의미합니까? 그 진술에 대해 조금 더 확장 할 수 있습니까?
David Arenburg

10
Badoe read.csv는 파일에서 테이블을 읽을 때 빈 셀을 NA로 변환 하도록 구성하는 방법을 자세히 설명 합니다. 그러나 질문의 ​​제목이 "빈 셀을"NA "로 변경"이므로 완전한 대답은 이미 data.frame이 환경에 있고 사용자가 빈 셀을 제거하려는 상황을 다루어야합니다.
Holger Brandl 2016 년

1
이것은 OP가 찾고 있던 것이 아닐 수도 있지만 빈 문자열과 NA를 포함하여 누락 된 값을 계산하는 데 도움이되었습니다. df %>% mutate_all(funs(empty_as_na)) %>% summarize_all(funs(sum(is.na(.))))dplyr은 널리 채택 될 수도 있고 그렇지 않을 수도 있지만 저를 포함한 많은 R 사용자 하위 집합에서 인기를 누리고 있으므로이 솔루션에 감사드립니다.
Dannid

22

이것은 트릭을 할 것입니다

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

1
나는 그것을 sf 객체에서 시도했고, 그것은 파싱 오류를 던졌다 : unknown WKB type 12. mutate가 기하학에서 무언가를 바꾸려고 시도한 것 같다.
aae

15

최근에 비슷한 문제가 발생했는데 이것이 저에게 효과적이었습니다.

변수가 숫자 df$Var[df$Var == ""] <- NA이면 간단한 것으로 충분합니다. 그러나 변수가 요인 인 경우 먼저 문자로 변환 한 다음 ""셀을 원하는 값으로 바꾸고 다시 요인으로 변환해야합니다. 따라서 귀하의 Sex변수가 요인이라고 가정하고 빈 셀을 바꾸려면 다음을 수행합니다.

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

3

내 함수는 외부 파일을 읽기 위해 haven 또는 foreign 패키지를 사용하는 경우 요인, 문자 벡터 및 잠재적 속성을 고려합니다. 또한 다른 자체 정의 na.string을 일치시킬 수 있습니다. 모든 열을 변환하려면 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

당신은 또한 사용할 수 mutate_at있는dplyr

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(.))))

(위의 dplyr 0.8.0) 에서 이것이 작성되어야하는 방식이 변경되었습니다. 그것이 전에 funs().funs (funs(name = f(.)). 대신 funs, 이제 우리는list (list(name = ~f(.)))

열 이름을 나열하는 훨씬 더 간단한 방법도 있습니다. (열 이름과 열 인덱스 모두 작동)

dat <- dat %>%
mutate_at(.vars = c("Age","Gender"),
    .funs = list(~ifelse(.=="", NA, as.character(.))))

2

위의 많은 옵션이 잘 작동하지만 대상이 아닌 변수의 강제 chr가 문제가 있음을 발견했습니다 . ifelseand greplwithin를 사용 lapply하면이 목표를 벗어난 효과가 해결됩니다 (제한된 테스트에서). 에서 slarky의 정규식 사용 grepl:

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] "숫자"


2

나는 모든 사람이 이미 답을 가지고 있다고 생각하지만 누군가가 찾아 오면 dplyr na_if ()가 (내 관점에서) 언급 된 것보다 더 효율적 일 것입니다.

# Import CSV, convert all 'blank' cells to NA
dat <- read.csv("data2.csv") %>% na_if("")

다음은 readr의 read_delim 함수를 활용하는 추가 접근 방식입니다. 방금 선택했습니다 (아마 널리 알고 있지만 향후 사용자를 위해 여기에 보관하겠습니다). csv 파일에서 모든 유형의 공백 및 NA 관련 값을 캡처 할 수 있으므로 위의 것보다 매우 간단하고 다양합니다.

dat <- read_csv("data2.csv", na = c("", "NA", "N/A"))

readr 버전과 Base R "."의 밑줄에 유의하십시오. read_csv에서.

바라건대 이것은 게시물을 방황하는 사람에게 도움이되기를 바랍니다!


0

그냥 사용할 수 없나요

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

데이터를 읽을 때 모든 공백을 NA로 변환해야합니다. 인용문 사이에 공백을 두어야합니다.


인용문 사이에 공백을 두지 않으면 어떻게됩니까?
Nneka

0

data.table 방식을 사용하는 솔루션에 대해 궁금한 사람들을 위해 다음은 Github에서 사용할 수있는 함수를 작성했습니다.

library(devtools)
source_url("https://github.com/YoannPa/Miscellaneous/blob/master/datatable_pattern_substitution.R?raw=TRUE")
dt.sub(DT = dat2, pattern = "^$|^ $",replacement = NA)
dat2

이 함수는 각 열을 통해 패턴 일치가 포함 된 열을 식별합니다. 그런 다음 gsub()패턴에 대한 일치를 포함하는 열에 만 적용되어 "^$|^ $"일치 항목을 NAs 로 대체 합니다.

이 기능을 계속 개선하여 더 빠르게 만들 것입니다.


0

이것은 나를 위해 작동합니다.

dataset <- read.csv(file = "data.csv",header=TRUE,fill = T,na.strings = "")

-3

r dplyr에서 설치하여 패키지 호출cran

library(dplyr)

(file)$(colname)<-sub("-",NA,file$colname) 

특정 열의 모든 빈 셀을 NA로 변환합니다.

열에 "-", "", 0이 포함되어 있으면 빈 셀 유형에 따라 코드에서 변경됩니다.

예를 들어 "-"대신 ""와 같은 빈 셀이 표시되면 다음 코드를 사용합니다.

(file)$(colname)<-sub("", NA, file$colname)

1
이 답변은 dplyr로드 한 후에 사용 되지 않으며 OP가 찾고있는 "모든 열"에 맞게 확장되지 않습니다.
Gregor Thomas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.