LoginSignup
3
2

More than 3 years have passed since last update.

RでNAを含む列を簡単に削除したい

Last updated at Posted at 2020-04-18

データ処理の前段階はデータを読み込むところから。ここで、手持ちのデータを読み込むと、しばしば空の列ができたり長さが揃っておらず不要な列ができて削除したいことがあります。次の表を読み込んだとします。

a b c d
1 2 3 NA
2 3 4 NA
3 4 NA NA
df <- data.frame(a = c(1,2,3),
                 b = c(2,3,4),
                 c = c(3,4,NA),
                 d = c(NA,NA,NA))
> df
  a b  c  d
1 1 2  3 NA
2 2 3  4 NA
3 3 4 NA NA

dplyr::select_ifを活用する

library(dplyr)

NAが含まれるかどうか調べるanyNA()を列ごとに適用し、返り値を論理ベクトルにして反転させる。

df %>% lapply(.,anyNA) %>% unlist %>% !.
    a     b     c     d 
 TRUE  TRUE FALSE FALSE 

これを、条件に合う列を選択する関数select_if()に渡す。

df %>% select_if(lapply(.,anyNA) %>% unlist %>% !.)
  a b
1 1 2
2 2 3
3 3 4

何とか1行のスクリプトで不要な列を削除できました。パイプのおかげで可読性もそんなに悪くないかと思います。

追記:purrr::negate()を活用する

@hkzm さんからのコメント参考になりました。

与えた関数の否定を渡すpurrr::negate()を使うとよりストレートに、シンプルに記述できました。

library(tidyverse)
df %>% select_if(negate(anyNA))
  a b
1 1 2
2 2 3
3 3 4

演算子!で反転させ、~でformulaにするのと同等です。

df %>% select_if(~ !anyNA(.))
  a b
1 1 2
2 2 3
3 3 4

可読性が良いのはpurrr::negate()を使う方かと個人的には思いました。

Pythonだと簡単なのに、Rだとなぜか苦労する

Pythonのpandasの場合、欠損値を削除するメソッドdropna()が用意されており、行方向と列方向の両方に適用可能です。

参考:pandasで欠損値NaNを除外(削除)・置換(穴埋め)・抽出

  • NAを1つでも含む列の削除
    • dropna(how='any', axis=1)
  • 全てNAの列の削除
    • dropna(how='all', axis=1)

ところが、Rだと欠損値を削除する関数は行方向のみです。

  • NAを1つでも含む行の削除
    • na.omit()

google検索かけて列方向で削除できる方法を探してなかなか見つかりませんでした。やっと見つけたのがこちらの記事。

RでNAを含む列を削除する手段

プログラミング言語により、得意不得意があるのかもしれません。なぜRで似たような関数がないのでしょうかね。

3
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2