source

NA만 포함된 열을 삭제하는 방법은 무엇입니까?

ittop 2023. 10. 14. 10:36
반응형

NA만 포함된 열을 삭제하는 방법은 무엇입니까?

모든 NA 값을 가진 일부 열을 포함하는 data.frame을 가지고 있습니다.data.frame에서 삭제하려면 어떻게 해야 합니까?

그 기능을 사용해도 되겠습니까?

na.omit(...) 

추가 인수 지정?

한 가지 방법:

df[, colSums(is.na(df)) != nrow(df)]

열의 NA 개수가 행 개수와 같으면, 전체 NA여야 합니다.

또는 마찬가지로

df[colSums(!is.na(df)) > 0]

애플리케이션 솔루션은 다음과 같습니다.

df %>% select_if(~sum(!is.na(.)) > 0)

업데이트: Thesummarise_if()기능은 현재 대체되었습니다.dplyr 1.0. 여기에 다음과 같은 두 가지 다른 솔루션이 있습니다.where()깔끔한 선택 기능:

df %>% 
  select(
    where(
      ~sum(!is.na(.x)) > 0
    )
  )
df %>% 
  select(
    where(
      ~!all(is.na(.x))
    )
  )

또 다른 옵션은janitor패키지:

df <- janitor::remove_empty(df, which = "cols")

https://github.com/sfirke/janitor

모두가 있는 열만 제거하려는 것 같습니다. NAs, 일부 행이 있는 열 남기기NAs. 나는 이렇게 할 것입니다 (그러나 나는 효율적인 벡터화된 부분이 있다고 확신합니다:

#set seed for reproducibility
set.seed <- 103
df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , vals = sample( c( 1:3 , NA ) , 10 , repl = TRUE ) )
df
#      id nas vals
#   1   1  NA   NA
#   2   2  NA    2
#   3   3  NA    1
#   4   4  NA    2
#   5   5  NA    2
#   6   6  NA    3
#   7   7  NA    2
#   8   8  NA    3
#   9   9  NA    3
#   10 10  NA    2

#Use this command to remove columns that are entirely NA values, it will leave columns where only some values are NA
df[ , ! apply( df , 2 , function(x) all(is.na(x)) ) ]
#      id vals
#   1   1   NA
#   2   2    2
#   3   3    1
#   4   4    2
#   5   5    2
#   6   6    3
#   7   7    2
#   8   8    3
#   9   9    3
#   10 10    2

만약 당신이 다음과 같은 것들이 있는 열들을 제거하고자 하는 상황에 놓여있는 것을 발견한다면.NA단순히 당신이 바꿀 수 있는 값들.all에 대한 위의 명령.any.

다음 옵션을 사용합니다.Filter

Filter(function(x) !all(is.na(x)), df)

참고: @Simon O'Hanlon의 게시물에서 나온 자료입니다.

직관적인 스크립트:dplyr::select_if(~!all(is.na(.))). 말 그대로 모든 요소가 누락되지 않은 열만 유지합니다.(모든 element-missing 열 삭제).

> df <- data.frame( id = 1:10 , nas = rep( NA , 10 ) , vals = sample( c( 1:3 , NA ) , 10 , repl = TRUE ) )

> df %>% glimpse()
Observations: 10
Variables: 3
$ id   <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
$ nas  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
$ vals <int> NA, 1, 1, NA, 1, 1, 1, 2, 3, NA

> df %>% select_if(~!all(is.na(.))) 
   id vals
1   1   NA
2   2    1
3   3    1
4   4   NA
5   5    1
6   6    1
7   7    1
8   8    2
9   9    3
10 10   NA

저는 성능이 정말 중요했기 때문에 위의 모든 기능을 벤치마킹했습니다.

참고: @Simon O'Hanlon의 게시물에서 나온 자료입니다.10 사이즈가 아닌 15000 사이즈만 가능합니다.

library(tidyverse)
library(microbenchmark)

set.seed(123)
df <- data.frame(id = 1:15000,
                 nas = rep(NA, 15000), 
                 vals = sample(c(1:3, NA), 15000,
                               repl = TRUE))
df

MadSconeF1 <- function(x) x[, colSums(is.na(x)) != nrow(x)]

MadSconeF2 <- function(x) x[colSums(!is.na(x)) > 0]

BradCannell <- function(x) x %>% select_if(~sum(!is.na(.)) > 0)

SimonOHanlon <- function(x) x[ , !apply(x, 2 ,function(y) all(is.na(y)))]

jsta <- function(x) janitor::remove_empty(x)

SiboJiang <- function(x) x %>% dplyr::select_if(~!all(is.na(.)))

akrun <- function(x) Filter(function(y) !all(is.na(y)), x)

mbm <- microbenchmark(
  "MadSconeF1" = {MadSconeF1(df)},
  "MadSconeF2" = {MadSconeF2(df)},
  "BradCannell" = {BradCannell(df)},
  "SimonOHanlon" = {SimonOHanlon(df)},
  "SiboJiang" = {SiboJiang(df)},
  "jsta" = {jsta(df)}, 
  "akrun" = {akrun(df)},
  times = 1000)

mbm

결과:

Unit: microseconds
         expr    min      lq      mean  median      uq      max neval  cld
   MadSconeF1  154.5  178.35  257.9396  196.05  219.25   5001.0  1000 a   
   MadSconeF2  180.4  209.75  281.2541  226.40  251.05   6322.1  1000 a   
  BradCannell 2579.4 2884.90 3330.3700 3059.45 3379.30  33667.3  1000    d
 SimonOHanlon  511.0  565.00  943.3089  586.45  623.65 210338.4  1000  b  
    SiboJiang 2558.1 2853.05 3377.6702 3010.30 3310.00  89718.0  1000    d
         jsta 1544.8 1652.45 2031.5065 1706.05 1872.65  11594.9  1000   c 
        akrun   93.8  111.60  139.9482  121.90  135.45   3851.2  1000 a


autoplot(mbm)

enter image description here

mbm %>% 
  tbl_df() %>%
  ggplot(aes(sample = time)) + 
  stat_qq() + 
  stat_qq_line() +
  facet_wrap(~expr, scales = "free")

enter image description here

다음과 같이 시도합니다.

df <- df[,colSums(is.na(df))<nrow(df)]

map_lgl 함수를 사용하는 또 다른 옵션.purrrpackage, 이것은 논리 벡터를 반환하고 사용합니다.[기둥을 떼다allNA. 재현 가능한 예는 다음과 같습니다.

set.seed(7)
df <- data.frame(id = 1:5 , nas = rep(NA, 5) , vals = sample(c(1:3,NA), 5, repl = TRUE))
df
#>   id nas vals
#> 1  1  NA    2
#> 2  2  NA    3
#> 3  3  NA    3
#> 4  4  NA   NA
#> 5  5  NA    3
library(purrr)
df[!map_lgl(df, ~ all(is.na(.)))]
#>   id vals
#> 1  1    2
#> 2  2    3
#> 3  3    3
#> 4  4   NA
#> 5  5    3

2022-08-28에 repex v2.0.2를 사용하여 생성됨

언급URL : https://stackoverflow.com/questions/15968494/how-to-delete-columns-that-contain-only-nas

반응형