Seçili sütunlar için bir tablodaki NA değerleri nasıl değiştirilir


82

NA değerlerini değiştirmeyle ilgili birçok gönderi var. Aşağıdaki tablo / çerçevedeki NA'ların aşağıdakilerle değiştirilebileceğinin farkındayım:

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

Ancak, bunu yalnızca belirli sütunlarla sınırlamak istersem ne olur? Size bir örnek göstereyim.

İlk olarak, bir veri kümesiyle başlayalım.

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

Hangi verir:

    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

Tamam, bu yüzden değiştirmeyi yalnızca 'a' ve 'b' sütunlarıyla sınırlamak istiyorum. Benim girişimim şuydu:

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

ve:

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

Hangi çalışmıyor.

Data.table girişimim, y<-data.table(x)açıkçası asla işe yaramayacaktı:

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

İs.na argümanının içindeki sütunları aktarmak istiyorum ama bu açıkçası işe yaramaz.

Bunu bir data.frame ve data.table içinde yapmak istiyorum. Nihai hedefim, mantıksal bir değişken olmadığı için 'c'yi olduğu gibi tutarken' a 've' b'de 1: 2'den 0: 1'e yeniden kodlamaktır. Bir sürü sütunum var, bu yüzden tek tek yapmak istemiyorum. Ve bunu nasıl yapacağımı bilmek istiyorum.

Önerin var mı?

Yanıtlar:


115

Yapabilirsin:

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

veya daha iyisi (IMHO), değişken adlarını kullanın:

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

Her iki durumda da, 1:2veya c("a", "b")önceden tanımlanmış bir vektör ile değiştirilebilir.


İş bu. Ya "1" i aramak istersem? Değiştirmeye çalıştım ama işe yaramadı.
jnam27

5
Muhtemelen şöyle:x[, 1:2][x[, 1:2] == 1] <- 0
flodel

@flodel datatable neden xsadece atama yaparken matrisi ilk üyesi olarak kabul ediyor? Bu özellik bir yerde belgelenmiş mi? Ayrıca ikinci örneğinizde sütun isimli vektörlerin önüne virgül koymayı unuttuğunuzu düşünüyorum.
ChiseledAbs

@ChiseledAbs, bence matris indekslemeden bahsediyorsunuz (buna örneğin stackoverflow.com/a/13999583/1201032 bakın ), ancak atamalarla sınırlı değildir, verileri çıkarmak için de kullanılabilir. Eksik virgülle ilgili olarak: hayır. Data.frames sütun listeleridir, bu nedenle için tek bir bağımsız değişken kullanırsanız [, belirtilen sütunları çıkarır (bkz. Stackoverflow.com/a/21137524/1201032 ). Umarım bu, sorunuzu yanıtlar, ancak gelecekte lütfen bunun gibi çok eski yanıtlar hakkında yorum yapmaktan kaçının; bunun yerine yeni bir soru gönderin.
flodel

In both cases, 1:2 or c("a", "b") can be replaced by a pre-defined vector.Bunun gibi önceden tanımlanmış bir vektör kullandığımda x[Vpredefined][is.na(x[Vpredefined])] <- 0hata veriyor
Rohit Saluja

30

Düzenle 2020-06-15

data.table1.12.4'ten (Ekim 2019) bu yana , data.tablebunu kolaylaştırmak için iki işlev kazanıyor: nafillve setnafill.

nafill sütunlar üzerinde çalışır:

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

setnafill tablolar üzerinde çalışır (değiştirmeler referansla / yerinde gerçekleşir)

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

Bu aynı zamanda diğer seçeneklerden daha verimli olacaktır; bkz ?nafillfazla, (LOCF) son gözlem-taşınan ve bir sonraki-gözlem gerçekleştirilmiştir-geriye doğru (NOCB) sürümlerini NAisnat zaman serisi.


Bu, data.tablesürümünüz için çalışacaktır :

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

David Arenburg aşağıda işaret ettiği gibi Alternatif olarak, kullanabilirsiniz set- (eğer üzerinde ya kullanabilirsiniz yan fayda data.frameya data.table:)

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

Bunun için teşekkürler. Sadece bilmek istedim, 3 yıl sonra, yukarıdakileri for döngüsü olmadan yapmanın bir yolu olup olmadığını? Bunun data.table ekibi tarafından daha özlü hale getirileceğini hayal ediyorum? Teşekkürler.
info_seekeR

1
@info_seekeR Daha kısa bir yol bilmiyorum
eddi

bu, flodel tarafından seçilen cevaptan daha iyi bir çözümdür. Flodel'in yaklaşımı atama operatörünü <- kullanır ve bu nedenle gereksiz veri kopyalamayı içerir.
Michael

@MichaelChirico Yorumunuzun ilk bölümünde out <- xsorudan x data.frame ile yanlış anlaşılmayı önlemek için bir adım eklediniz mi? Aksi takdirde, bu daha da kısa bir komuttur: y[, (cols):=lapply(.SD, function(i){i[is.na(i)] <- 0; i}), .SDcols = cols]'out' değişken adını atlamak ve 'x' kullanmak.
Yoann Pageaud

@MichaelChirico Doğru! Tamamen nafill'i unuttum ()
Yoann Pageaud

22

@Robert McDonald'ın tidyr::replace_na()cevabına dayanarak , aşağıda dplyrhangi sütunların NAdeğiştirileceğini kontrol etmek için bazı seçenekler verilmiştir :

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
Bu fonksiyon ile Hata alıyorum: Error in replace_na(., 0) : argument "value" is missing, with no default. Neyin değiştirileceğine dair herhangi bir öneriniz var mı?
Tim M.Schendzielorz

17

Bu artık tidyr'de replace_na () ile önemsizdir. İşlev, data.tables ve data.frames için çalışıyor gibi görünüyor:

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

2

Bunun daha kısa olup olmadığından emin değilim, ancak bu işlev aynı zamanda bir data.table'ın seçilen sütunlarında NA'ların (veya istediğiniz herhangi bir değerin) değiştirilmesini bulup buna izin verecektir:

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
}

Uygulamak için:

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

İşlev, giriş kriterlerini karşılayan (bu durumda is.na == TRUE) seçilen sütun ve satırlardan (hücre koordinatları) oluşan bir matris oluşturur.


1

Fonksiyon data.tableile bir şekilde çözebiliriz tidyr::repalce_navelapply

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")]

Bu şekilde, yapıştırma sütunlarını NAstring ile de çözebiliriz . Önce biz replace_na(x,""), sonra stringr::str_csütunları birleştirmek için kullanabiliriz !


1
Sınırlı ve anında yardım sağlayabilecek bu kod parçacığı için teşekkür ederiz. Bir Doğru bir açıklama ölçüde bu soruna iyi bir çözüm olmasının nedeni göstererek uzun vadeli değerini artıracak ve diğer benzer sorularla gelecek okuyucularına daha kullanışlı bir hale getirecektir. Yaptığınız varsayımlar da dahil olmak üzere bazı açıklamalar eklemek için lütfen cevabınızı düzenleyin .
CertainPerformance

0

Belirli bir sütun için, bir alternatif var 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} ve {stringr} ile oldukça kullanışlıdır

library(data.table)
library(stringr)

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

Bilginize


0

Data.table y'den başlayarak, şunu yazabilirsiniz: Bu komutu oluşturup çalıştırmadan önce
y[, (cols):=lapply(.SD, function(i){i[is.na(i)] <- 0; i}), .SDcols = cols]
bunu unutmayın .library(data.table)y


-4

bu benim için iyi çalışıyor

DataTable DT = new DataTable();

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

1
bu R mi? C # gibi görünüyor
Chris McKelt
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.