Bir veri çerçevesi var ve bazı sütunların NA
değerleri var.
Bu NA
değerleri sıfırlarla nasıl değiştiririm ?
Bir veri çerçevesi var ve bazı sütunların NA
değerleri var.
Bu NA
değerleri sıfırlarla nasıl değiştiririm ?
Yanıtlar:
@ Gsk3 yanıtındaki yorumuma bakın. Basit bir örnek:
> m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10)
> d <- as.data.frame(m)
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 4 3 NA 3 7 6 6 10 6 5
2 9 8 9 5 10 NA 2 1 7 2
3 1 1 6 3 6 NA 1 4 1 6
4 NA 4 NA 7 10 2 NA 4 1 8
5 1 2 4 NA 2 6 2 6 7 4
6 NA 3 NA NA 10 2 1 10 8 4
7 4 4 9 10 9 8 9 4 10 NA
8 5 8 3 2 1 4 5 9 4 7
9 3 9 10 1 9 9 10 5 3 3
10 4 2 2 5 NA 9 7 2 5 5
> d[is.na(d)] <- 0
> d
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 4 3 0 3 7 6 6 10 6 5
2 9 8 9 5 10 0 2 1 7 2
3 1 1 6 3 6 0 1 4 1 6
4 0 4 0 7 10 2 0 4 1 8
5 1 2 4 0 2 6 2 6 7 4
6 0 3 0 0 10 2 1 10 8 4
7 4 4 9 10 9 8 9 4 10 0
8 5 8 3 2 1 4 5 9 4 7
9 3 9 10 1 9 9 10 5 3 3
10 4 2 2 5 0 9 7 2 5 5
Başvurmaya gerek yok apply
. =)
DÜZENLE
norm
Pakete de bir göz atmalısınız . Eksik veri analizi için çok güzel özelliklere sahiptir. =)
df[19:28][is.na(df[19:28])] <- 0
Dplyr hibridize seçenekleri artık Base R alt kümesinin yeniden atamasından% 30 daha hızlı. 100M veri noktasında veri çerçevesi mutate_all(~replace(., is.na(.), 0))
, temel R d[is.na(d)] <- 0
seçeneğinden yarım saniye daha hızlı çalışır . Özellikle kaçınmak istediği şey bir ifelse()
veya bir kullanmaktır if_else()
. (600 deneme analizinin tamamı, çoğunlukla bu yaklaşımların dahil edilmesinden ötürü 4,5 saatten fazla sürdü.) Tam sonuçlar için lütfen aşağıdaki karşılaştırma analizlerine bakın.
Devasa veri çerçeveleri ile mücadele ediyorsanız, data.table
en hızlı seçenek budur: standart Base R yaklaşımından % 40 daha hızlı . Ayrıca, verileri yerinde değiştirerek, aynı anda verilerin neredeyse iki katı kadar etkili bir şekilde çalışmanıza olanak tanır.
locationally:
mutate_at(c(5:10), ~replace(., is.na(.), 0))
mutate_at(vars(var5:var10), ~replace(., is.na(.), 0))
mutate_at(vars(contains("1")), ~replace(., is.na(.), 0))
contains()
, deneyin ends_with()
,starts_with()
mutate_at(vars(matches("\\d{2}")), ~replace(., is.na(.), 0))
Şartlı olarak:
(yalnızca tek bir türü değiştirin ve diğer türleri yalnız bırakın.)
mutate_if(is.integer, ~replace(., is.na(.), 0))
mutate_if(is.numeric, ~replace(., is.na(.), 0))
mutate_if(is.character, ~replace(., is.na(.), 0))
Dplyr 0.8.0 için güncellendi: fonksiyonlar purrr format ~
sembollerini kullanıyor: kullanımdan kaldırıldıfuns()
argümanların .
# Base R:
baseR.sbst.rssgn <- function(x) { x[is.na(x)] <- 0; x }
baseR.replace <- function(x) { replace(x, is.na(x), 0) }
baseR.for <- function(x) { for(j in 1:ncol(x))
x[[j]][is.na(x[[j]])] = 0 }
# tidyverse
## dplyr
dplyr_if_else <- function(x) { mutate_all(x, ~if_else(is.na(.), 0, .)) }
dplyr_coalesce <- function(x) { mutate_all(x, ~coalesce(., 0)) }
## tidyr
tidyr_replace_na <- function(x) { replace_na(x, as.list(setNames(rep(0, 10), as.list(c(paste0("var", 1:10)))))) }
## hybrid
hybrd.ifelse <- function(x) { mutate_all(x, ~ifelse(is.na(.), 0, .)) }
hybrd.replace_na <- function(x) { mutate_all(x, ~replace_na(., 0)) }
hybrd.replace <- function(x) { mutate_all(x, ~replace(., is.na(.), 0)) }
hybrd.rplc_at.idx<- function(x) { mutate_at(x, c(1:10), ~replace(., is.na(.), 0)) }
hybrd.rplc_at.nse<- function(x) { mutate_at(x, vars(var1:var10), ~replace(., is.na(.), 0)) }
hybrd.rplc_at.stw<- function(x) { mutate_at(x, vars(starts_with("var")), ~replace(., is.na(.), 0)) }
hybrd.rplc_at.ctn<- function(x) { mutate_at(x, vars(contains("var")), ~replace(., is.na(.), 0)) }
hybrd.rplc_at.mtc<- function(x) { mutate_at(x, vars(matches("\\d+")), ~replace(., is.na(.), 0)) }
hybrd.rplc_if <- function(x) { mutate_if(x, is.numeric, ~replace(., is.na(.), 0)) }
# data.table
library(data.table)
DT.for.set.nms <- function(x) { for (j in names(x))
set(x,which(is.na(x[[j]])),j,0) }
DT.for.set.sqln <- function(x) { for (j in seq_len(ncol(x)))
set(x,which(is.na(x[[j]])),j,0) }
DT.nafill <- function(x) { nafill(df, fill=0)}
DT.setnafill <- function(x) { setnafill(df, fill=0)}
library(microbenchmark)
# 20% NA filled dataframe of 10 Million rows and 10 columns
set.seed(42) # to recreate the exact dataframe
dfN <- as.data.frame(matrix(sample(c(NA, as.numeric(1:4)), 1e7*10, replace = TRUE),
dimnames = list(NULL, paste0("var", 1:10)),
ncol = 10))
# Running 600 trials with each replacement method
# (the functions are excecuted locally - so that the original dataframe remains unmodified in all cases)
perf_results <- microbenchmark(
hybrid.ifelse = hybrid.ifelse(copy(dfN)),
dplyr_if_else = dplyr_if_else(copy(dfN)),
hybrd.replace_na = hybrd.replace_na(copy(dfN)),
baseR.sbst.rssgn = baseR.sbst.rssgn(copy(dfN)),
baseR.replace = baseR.replace(copy(dfN)),
dplyr_coalesce = dplyr_coalesce(copy(dfN)),
tidyr_replace_na = tidyr_replace_na(copy(dfN)),
hybrd.replace = hybrd.replace(copy(dfN)),
hybrd.rplc_at.ctn= hybrd.rplc_at.ctn(copy(dfN)),
hybrd.rplc_at.nse= hybrd.rplc_at.nse(copy(dfN)),
baseR.for = baseR.for(copy(dfN)),
hybrd.rplc_at.idx= hybrd.rplc_at.idx(copy(dfN)),
DT.for.set.nms = DT.for.set.nms(copy(dfN)),
DT.for.set.sqln = DT.for.set.sqln(copy(dfN)),
times = 600L
)
> print(perf_results) Unit: milliseconds expr min lq mean median uq max neval hybrd.ifelse 6171.0439 6339.7046 6425.221 6407.397 6496.992 7052.851 600 dplyr_if_else 3737.4954 3877.0983 3953.857 3946.024 4023.301 4539.428 600 hybrd.replace_na 1497.8653 1706.1119 1748.464 1745.282 1789.804 2127.166 600 baseR.sbst.rssgn 1480.5098 1686.1581 1730.006 1728.477 1772.951 2010.215 600 baseR.replace 1457.4016 1681.5583 1725.481 1722.069 1766.916 2089.627 600 dplyr_coalesce 1227.6150 1483.3520 1524.245 1519.454 1561.488 1996.859 600 tidyr_replace_na 1248.3292 1473.1707 1521.889 1520.108 1570.382 1995.768 600 hybrd.replace 913.1865 1197.3133 1233.336 1238.747 1276.141 1438.646 600 hybrd.rplc_at.ctn 916.9339 1192.9885 1224.733 1227.628 1268.644 1466.085 600 hybrd.rplc_at.nse 919.0270 1191.0541 1228.749 1228.635 1275.103 2882.040 600 baseR.for 869.3169 1180.8311 1216.958 1224.407 1264.737 1459.726 600 hybrd.rplc_at.idx 839.8915 1189.7465 1223.326 1228.329 1266.375 1565.794 600 DT.for.set.nms 761.6086 915.8166 1015.457 1001.772 1106.315 1363.044 600 DT.for.set.sqln 787.3535 918.8733 1017.812 1002.042 1122.474 1321.860 600
ggplot(perf_results, aes(x=expr, y=time/10^9)) +
geom_boxplot() +
xlab('Expression') +
ylab('Elapsed Time (Seconds)') +
scale_y_continuous(breaks = seq(0,7,1)) +
coord_flip()
qplot(y=time/10^9, data=perf_results, colour=expr) +
labs(y = "log10 Scaled Elapsed Time per Trial (secs)", x = "Trial Number") +
coord_cartesian(ylim = c(0.75, 7.5)) +
scale_y_log10(breaks=c(0.75, 0.875, 1, 1.25, 1.5, 1.75, seq(2, 7.5)))
Veri setleri büyüdükçe, Tidyr 'ler replace_na
tarihsel olarak öne çıkmıştı. Mevcut 100M veri noktalarının toplanmasıyla, neredeyse tam olarak ve Döngü için bir Base R gerçekleştirir . Farklı boyutlardaki veri çerçeveleri için neler olduğunu merak ediyorum.
mutate
Ve summarize
_at
ve _all
işlev değişkenleri için ek örnekler burada bulunabilir: https://rdrr.io/cran/dplyr/man/summarise_all.html
Ayrıca, burada yararlı gösteriler ve örnek koleksiyonları buldum: https: //blog.exploratory. io /-korku-heres-neden-be095fd4eb8a dplyr-0-5 olduğu
Özel teşekkürler:
local()
(ve Frank'in hasta yardımı ile) sessiz zorlamanın bu yaklaşımların çoğunu hızlandırma rolünü anlamama yardımcı olduğu için çalışmaktadır . coalesce()
işlev eklemek ve analizi güncellemek için.data.table
sonunda nihayet onları dizilime dahil edecek kadar iyi fonksiyonlar bulması için .is.numeric()
gerçekten test ettiğini açıkladığı için Roman .(Elbette, bu yaklaşımları yararlı bulursanız, lütfen onlara ulaşın ve onlara oy verin.)
Numerics kullanımımla ilgili not: Saf bir tamsayı veri kümeniz varsa, tüm işlevleriniz daha hızlı çalışır. Dahafazla bilgi içinlütfen alexiz_laz'ın çalışmasına bakın. IRL,% 10-15'ten fazla tamsayı içeren bir veri kümesiyle karşılaştığımı hatırlayamıyorum, bu yüzden bu testleri tamamen sayısal veri çerçeveleri üzerinde çalıştırıyorum.
Kullanılan Donanım 24 GB RAM ile 3.9 GHz CPU
df1[j][is.na(df1[j])] = 0
yanlış, olmalıdf1[[j]][is.na(df1[[j]])] = 0
forLp_Sbst
kimsenin ona yaklaşmayı düşünmesi gereken bir yol gibi görünmüyorforLp_smplfSbst
coalesce()
Seçeneği ekledim ve her zaman yeniden çalıştırdım. Dürtünün güncellenmesi için teşekkür ederim.
Tek bir vektör için:
x <- c(1,2,NA,4,5)
x[is.na(x)] <- 0
Bir data.frame için, yukarıdakilerden bir işlev yapın ve ardından apply
sütunlara getirin.
Lütfen bir dahaki sefere burada ayrıntılı olarak açıklandığı gibi tekrarlanabilir bir örnek verin:
is.na
, genel bir işlevdir ve data.frame
sınıf nesneleri için yöntemlere sahiptir . yani bu da data.frame
s üzerinde çalışacaktır !
methods(is.na)
ilk kez, ben gibiydi whaaa?!? . Böyle şeyler olduğunda seviyorum! =)
dplyr örneği:
library(dplyr)
df1 <- df1 %>%
mutate(myCol1 = if_else(is.na(myCol1), 0, myCol1))
Not: Bu, seçilen sütun başına işe yarar, eğer bunu tüm sütun için yapmamız gerekiyorsa, @reidjax'ın mutate_each kullanarak yanıtına bakın .
Sorunun zaten cevaplandığını biliyorum, ancak bu şekilde yapmak bazıları için daha yararlı olabilir:
Bu işlevi tanımlayın:
na.zero <- function (x) {
x[is.na(x)] <- 0
return(x)
}
Artık bir vektördeki NA'ları sıfıra dönüştürmeniz gerektiğinde şunları yapabilirsiniz:
na.zero(some.vector)
İle dplyr
0.5.0, kullanabilirsiniz coalesce
kolayca entegre edilebilir işlevini %>%
yaparak boru hattının coalesce(vec, 0)
. Bu, tüm NA'ları vec
0 ile değiştirir :
Diyelim ki NA
s olan bir veri çerçevemiz var :
library(dplyr)
df <- data.frame(v = c(1, 2, 3, NA, 5, 6, 8))
df
# v
# 1 1
# 2 2
# 3 3
# 4 NA
# 5 5
# 6 6
# 7 8
df %>% mutate(v = coalesce(v, 0))
# v
# 1 1
# 2 2
# 3 3
# 4 0
# 5 5
# 6 6
# 7 8
replace()
Değiştirmek için matris veya vektörde daha genel bir yaklaşımNA
için0
Örneğin:
> x <- c(1,2,NA,NA,1,1)
> x1 <- replace(x,is.na(x),0)
> x1
[1] 1 2 0 0 1 1
Bu aynı zamanda ifelse()
içinde kullanmak için bir alternatiftir .dplyr
df = data.frame(col = c(1,2,NA,NA,1,1))
df <- df %>%
mutate(col = replace(col,is.na(col),0))
levels(A$x) <- append(levels(A$x), "notAnswered") A$x <- replace(A$x,which(is.na(A$x)),"notAnswered")
which
burada gerekli değil, kullanabilirsiniz x1 <- replace(x,is.na(x),1)
.
NA
için 0
büyük bir veri çerçevesi içinde sadece bir spesifik sütunda ve bu fonksiyon replace()
en etkili da ise en basit çalıştı.
Faktör değişkenlerindeki NA'ları değiştirmek istiyorsanız, bu yararlı olabilir:
n <- length(levels(data.vector))+1
data.vector <- as.numeric(data.vector)
data.vector[is.na(data.vector)] <- n
data.vector <- as.factor(data.vector)
levels(data.vector) <- c("level1","level2",...,"leveln", "NAlevel")
Bir faktör-vektörü sayısal bir vektöre dönüştürür ve başka bir yapay sayısal faktör seviyesi ekler, bu daha sonra seçtiğiniz bir ekstra "NA-seviyesi" ile bir faktör-vektörüne geri dönüştürülür.
@ İanmunoz'un gönderisine yorum yapmıştım ama yeterli itibarım yok. Birleştirebilirsiniz dplyr
's mutate_each
ve replace
özen NA
için 0
değiştirilmesi. @ AL3xa'nın cevabındaki veri çerçevesini kullanarak ...
> m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10)
> d <- as.data.frame(m)
> d
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 4 8 1 9 6 9 NA 8 9 8
2 8 3 6 8 2 1 NA NA 6 3
3 6 6 3 NA 2 NA NA 5 7 7
4 10 6 1 1 7 9 1 10 3 10
5 10 6 7 10 10 3 2 5 4 6
6 2 4 1 5 7 NA NA 8 4 4
7 7 2 3 1 4 10 NA 8 7 7
8 9 5 8 10 5 3 5 8 3 2
9 9 1 8 7 6 5 NA NA 6 7
10 6 10 8 7 1 1 2 2 5 7
> d %>% mutate_each( funs_( interp( ~replace(., is.na(.),0) ) ) )
V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1 4 8 1 9 6 9 0 8 9 8
2 8 3 6 8 2 1 0 0 6 3
3 6 6 3 0 2 0 0 5 7 7
4 10 6 1 1 7 9 1 10 3 10
5 10 6 7 10 10 3 2 5 4 6
6 2 4 1 5 7 0 0 8 4 4
7 7 2 3 1 4 10 0 8 7 7
8 9 5 8 10 5 3 5 8 3 2
9 9 1 8 7 6 5 0 0 6 7
10 6 10 8 7 1 1 2 2 5 7
Burada standart değerlendirme (SE) kullanıyoruz, bu yüzden " funs_
." Ayrıca lazyeval
's interp
/ ~
ve ' .
birlikte çalıştığımız her şey ' referanslarını, yani veri çerçevesini kullanıyoruz. Şimdi sıfırlar var!
Kullanabilirsiniz replace()
Örneğin:
> x <- c(-1,0,1,0,NA,0,1,1)
> x1 <- replace(x,5,1)
> x1
[1] -1 0 1 0 1 0 1 1
> x1 <- replace(x,5,mean(x,na.rm=T))
> x1
[1] -1.00 0.00 1.00 0.00 0.29 0.00 1.00 1.00
NA
vektörünüzdeki s dizinini bildiğinizde pratiktir . Örneğinizdeki gibi küçük vektörler için uygundur.
x1 <- replace(x,is.na(x),1)
, dizin değerlerini açıkça listelemeden çalışacaktır.
Birkaç sütun için çalışan yöntemle başka bir dplyr
boru uyumlu seçenek :tidyr
replace_na
require(dplyr)
require(tidyr)
m <- matrix(sample(c(NA, 1:10), 100, replace = TRUE), 10)
d <- as.data.frame(m)
myList <- setNames(lapply(vector("list", ncol(d)), function(x) x <- 0), names(d))
df <- d %>% replace_na(myList)
Örneğin sayısal sütunlarla kolayca kısıtlayabilirsiniz:
d$str <- c("string", NA)
myList <- myList[sapply(d, is.numeric)]
df <- d %>% replace_na(myList)
Bu amaç için özel işlev ( nafill
/ setnafill
) son data.table
sürümdedir
install.packages("data.table", repos="https://Rdatatable.gitlab.io/data.table")
library(data.table)
ans_df = nafill(df, fill=0)
setnafill(df, fill=0) # this one updates in-place
Datacamp'tan çıkarılan bu basit işlev yardımcı olabilir:
replace_missings <- function(x, replacement) {
is_miss <- is.na(x)
x[is_miss] <- replacement
message(sum(is_miss), " missings replaced by the value ", replacement)
x
}
Sonra
replace_missings(df, replacement = 0)
Bir veri çerçevesindeki tüm NA'ları değiştirmek için şunları kullanabilirsiniz:
df %>% replace(is.na(.), 0)
bu örnek V3 sütunundaki belirli bir sütundaki NA'ları değiştirdikten sonra yeni bir ad atamak istiyorsanız, bunu da kullanabilirsiniz
my.data.frame$the.new.column.name <- ifelse(is.na(my.data.frame$V3),0,1)