選択した列のテーブルのNA値を置き換える方法


82

NA値の置き換えに関する投稿はたくさんあります。次のテーブル/フレームのNAを次のように置き換えることができることを認識しています。

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

しかし、特定の列のみに制限したい場合はどうなりますか?例を示しましょう。

まず、データセットから始めましょう。

set.seed(1234)
x <- data.frame(a=sample(c(1,2,NA), 10, replace=T),
                b=sample(c(1,2,NA), 10, replace=T), 
                c=sample(c(1:5,NA), 10, replace=T))

それは与える:

    a  b  c
1   1 NA  2
2   2  2  2
3   2  1  1
4   2 NA  1
5  NA  1  2
6   2 NA  5
7   1  1  4
8   1  1 NA
9   2  1  5
10  2  1  1

わかりました。置換を列「a」と「b」に限定したいと思います。私の試みは:

x[is.na(x), 1:2]<-0

そして:

x[is.na(x[1:2])]<-0

これは機能しません。

私のdata.tableの試みはy<-data.table(x)、明らかに機能しませんでした。

y[is.na(y[,list(a,b)]), ]

is.na引数内に列を渡したいのですが、それは明らかに機能しません。

data.frameとdata.tableでこれを実行したいと思います。私の最終目標は、論理変数ではないため、「c」をそのままにして、「a」と「b」の1:2を0:1に再コーディングすることです。列がたくさんあるので、1つずつやりたくありません。そして、私はこれを行う方法を知りたいだけです。

何か提案はありますか?

回答:


115

できるよ:

x[, 1:2][is.na(x[, 1:2])] <- 0

以上(IMHO)、変数名を使用します。

x[c("a", "b")][is.na(x[c("a", "b")])] <- 0

どちらの場合も、1:2またはc("a", "b")事前定義されたベクトルで置き換えることができます。


それは仕事をします。「1」を検索したい場合はどうなりますか?変更しようとしましたが、動作しませんでした。
jnam27 2013年

5
おそらくこのように:x[, 1:2][x[, 1:2] == 1] <- 0
flodel 2013年

@flodel割り当てをx行う場合にのみ、データテーブルが最初のメンバーとして行列を受け入れるのはなぜですか?この機能はどこかに文書化されていますか?また、2番目の例では、列名の付いたベクトルの前にコンマを付けるのを忘れたと思います。
ChiseledAbs 2016

@ChiseledAbs、マトリックスインデックスを参照していると思いますが(たとえば、stackoverflow.com / a / 13999583/1201032を参照)、割り当てに限定されず、データの抽出にも使用できます。欠落しているコンマについて:いいえ。Data.framesは列のリストであるため、に単一の引数を使用する[と、指定された列が抽出されます(stackoverflow.com/a/21137524/1201032を参照)。これがあなたの質問に答えることを願っていますが、将来的には、このような非常に古い答えにコメントすることは避けてください。代わりに、新しい質問を投稿してください。
flodel 2016

In both cases, 1:2 or c("a", "b") can be replaced by a pre-defined vector.このような事前定義されたベクトルを使用すると、x[Vpredefined][is.na(x[Vpredefined])] <- 0エラーが発生します
Rohit Saluja 2018

30

2020-06-15を編集

data.table1.12.4(2019年10月)以降、data.tableこれを容易にする2つの関数を取得します:nafillおよびsetnafill

nafill 列を操作します:

cols = c('a', 'b')
y[ , (cols) := lapply(.SD, nafill, fill=0), .SDcols = cols]

setnafill テーブルで動作します(置換は参照/インプレースで行われます)

setnafill(y, cols=cols, fill=0)
# print y to show the effect
y[]

これは、他のオプションよりも効率的です。詳細について?nafillNA、時系列の代入の最後の観測が繰り越された(LOCF)バージョンと次の観測が繰り越された(NOCB)バージョンを参照してください。


これはお使いのdata.tableバージョンで機能します。

for (col in c("a", "b")) y[is.na(get(col)), (col) := 0]

または、David Arenburgが以下で指摘しているように、次を使用できますset(副次的な利点-data.frameまたはで使用できますdata.table)。

for (col in 1:2) set(x, which(is.na(x[[col]])), col, 0)

これをありがとう。forループなしで上記を実行する方法があるかどうか、3年後に知りたかっただけですか?これはdata.tableチームによってもっと簡潔にされたと思いますか?ありがとう。
info_seekeR 2016年

1
@info_seekeRもっと簡潔な方法はわかりません
eddi 2016年

これは、flodelによって選択された回答よりも優れたソリューションです。Flodelのアプローチでは、代入演算子<-を使用するため、不要なデータのコピーが必要になります。
マイケル

@MichaelChiricoコメントの最初の部分でout <- x、質問のx data.frameの誤解を避けるための手順を追加しましたか?それ以外の場合、これはさらに短いコマンドです。y[, (cols):=lapply(.SD, function(i){i[is.na(i)] <- 0; i}), .SDcols = cols]「out」変数名をスキップし、「x」を使用します。
YoannPageaud20年

@MichaelChirico True!nafill()を完全に忘れました
YoannPageaud20年

22

@Robert McDonaldのtidyr::replace_na()回答にdplyr基づいて、どの列NAを置き換えるかを制御するためのいくつかのオプションを次に示します。

library(tidyverse)

# by column type:
x %>%
  mutate_if(is.numeric, ~replace_na(., 0))

# select columns defined in vars(col1, col2, ...):
x %>%
  mutate_at(vars(a, b, c), ~replace_na(., 0))

# all columns:
x %>%
  mutate_all(~replace_na(., 0))

1
この関数を使用すると、エラーが発生します: Error in replace_na(., 0) : argument "value" is missing, with no default。何を変更するべきか提案はありますか?
Tim M.Schendzielorz19年

17

これは、replace_na()を使用したtidyrでは簡単です。この関数は、data.tablesとdata.framesで機能するようです。

tidyr::replace_na(x, list(a=0, b=0))

2

これがより簡潔であるかどうかはわかりませんが、この関数は、data.tableの選択された列のNA(または任意の値)を見つけて置き換えることもできます。

update.mat <- function(dt, cols, criteria) {
  require(data.table)
  x <- as.data.frame(which(criteria==TRUE, arr.ind = TRUE))
  y <- as.matrix(subset(x, x$col %in% which((names(dt) %in% cols), arr.ind = TRUE)))
  y
}

それを適用するには:

y[update.mat(y, c("a", "b"), is.na(y))] <- 0

この関数は、入力基準(この場合はis.na == TRUE)を満たす、選択された列と行(セル座標)の行列を作成します。


1

関数とdata.table方法でそれを解決することができtidyr::repalce_naますlapply

library(data.table)
library(tidyr)
setDT(df)
df[,c("a","b","c"):=lapply(.SD,function(x) replace_na(x,0)),.SDcols=c("a","b","c")]

このようにして、NA文字列を使用して列の貼り付けを解決することもできます。まず、列を組み合わせるreplace_na(x,"")ために使用できstringr::str_cます。


1
このコードスニペットをありがとうございます。これは、限られた即時のヘルプを提供する可能性があります。適切な説明が大幅にこれは問題に良い解決策であり、他、同様の質問を将来の読者にそれがより便利になるだろう、なぜ示すことによって、その長期的な価値を向上させるであろう。あなたが行った仮定を含むいくつかの説明を追加するためにあなたの答えを編集してください。
特定のパフォーマンス

0

特定の列については、 sapply

DF <- data.frame(A = letters[1:5],
             B = letters[6:10],
             C = c(2, 5, NA, 8, NA))

DF_NEW <- sapply(seq(1, nrow(DF)),
                    function(i) ifelse(is.na(DF[i,3]) ==
                                       TRUE,
                                       0,
                                       DF[i,3]))

DF[,3] <- DF_NEW
DF

0

{data.table}と{stringr}で非常に便利です

library(data.table)
library(stringr)

x[, lapply(.SD, function(xx) {str_replace_na(xx, 0)})]

ご参考までに


0

data.table yから始めて、次のように書くことができます。このコマンドを作成して実行
y[, (cols):=lapply(.SD, function(i){i[is.na(i)] <- 0; i}), .SDcols = cols]
するlibrary(data.table)前に忘れないでくださいy


-4

これは私にとってはうまくいきます

DataTable DT = new DataTable();

DT = DT.AsEnumerable().Select(R =>
{
      R["Campo1"] = valor;
      return (R);
}).ToArray().CopyToDataTable();

1
これはRですか?C#のように見えます
Chris McKelt 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.