R で NA をゼロに置き換える

Gustavo du Mortier 2023年1月30日
  1. 大きな R データフレームの NA を 0 に置き換える
  2. R データフレームのサブセット内の NA を 0 に置き換える
R で NA をゼロに置き換える

R でデータフレーム内の NA をゼロに置き換える簡単な方法があります。そのデータフレーム内のすべての NA の値をゼロに置き換えるには、次のような文を実行します。

my_data[is.na(my_data)] <- 0

例えば、my_data に以下のような内容があったとします。

   C1  C2    C3  C4  C5
1   4   3  <NA>   3   7
2   9   8   ABC   5  10
3   1   1   XYZ   3   6
4  NA   4  <NA>   7  10
5   1   2   ZC1  NA   2

my_data[is.na(my_data)] <- 0 を実行すると、データフレームの内容は以下のようになります。

   C1  C2    C3  C4  C5
1   4   3     0   3   7
2   9   8   ABC   5  10
3   1   1   XYZ   3   6
4   0   4     0   7  10
5   1   2   ZC1   0   2

大きな R データフレームの NA を 0 に置き換える

以前のソリューションでは Base R のサブセット再割り当てを使用していましたが、比較的小さなデータフレームがある場合には問題なく動作します。しかし、より大きなデータセットの場合は、dplyr パッケージの最近のバージョンで実装された新しいハイブリッド評価アプローチのような、より高速な代替手段が必要になるかもしれません。

dplyr パッケージで採用されている新しいアプローチは、式全体を認識し、それらを評価するために C++ コードを使用します。このようにして、ビッグデータフレームを処理する際の変換速度を最大 30%向上させることができます。

dplyr パッケージを用いて NA の値をゼロに置き換えるには、以下の例のように、スコープ付き動詞 _all を用いた mutate 関数と purrr 形式の replace 関数を利用します。

my_data <- mutate_all(my_data, ~replace(., is.na(.), 0))

purrr 記法を用いることで、replace 関数を各データフレーム要素に適用することができます。

R データフレームのサブセット内の NA を 0 に置き換える

関数 mutate のスコープ付き動詞 _all の代わりに、_at のスコープ付き動詞を用いて特定のカラムに置換処理を限定することができます。そのためには、置換を適用したい列の名前をベクトルに含めることができます。先ほどのデータフレームを用いて、C1C4 の列にある NA の値のみを置換する必要がある場合は、以下のコマンドを用いることができます。

my_data <- mutate_at(my_data, c(`C1`、`C4`), ~replace(., is.na(.), 0))

この方法では、列 C1C4 の NA のみが 0 で置換され、結果として以下のようなデータフレームが得られます。

   C1  C2    C3  C4  C5
1   4   3  <NA>   3   7
2   9   8   ABC   5  10
3   1   1   XYZ   3   6
4   0   4  <NA>   7  10
5   1   2   ZC1   0   2

先ほどの例では、C3 のような英数字列にゼロ値が含まれるのを避けるために、NA を数値列のみゼロに置き換えたいと思ったかもしれません。その場合は、置換を適用したい列を指定する代わりに is.numeric 条件を指定して mutate_if 関数を用いて NA を数値列のみでゼロに置換するように R に指示することができます。以下の例では、dplyr パッケージをインストールしてデータフレームを生成し、置換を実行して結果を表示するまでの完全なコードを示しています。

install.packages("dplyr")
library(dplyr)
C1 <- c(4, 9, 1, NA, 1)
C2 <- c(3, 8, 1, 4, 2)
C3 <- c(NA, 'ABC', 'XYZ', NA, 'ZC1')
C4 <- c(3, 5, 3, 7, NA)
C5 <- c(7, 10, NA, 10, 2)
my_data <- data.frame(C1, C2, C3, C4, C5)
my_data <- mutate_if(my_data, is.numeric, ~replace(., is.na(.), 0))
my_data

出力:

   C1  C2    C3  C4  C5
1   4   3  <NA>   3   7
2   9   8   ABC   5  10
3   1   1   XYZ   3   0
4   0   4  <NA>   7  10
5   1   2   ZC1   0   2

関数 mutate() とそのバリエーションの詳細については、R ドキュメントを参照してください。

関連記事 - R Data Frame