Am un cadru de date și unele coloane au " NA " valori.
Cum pot înlocui aceste " NA " valorile cu zerouri?
Vezi comentariul meu de la @gsk3 răspuns. Un exemplu simplu:
> 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
Nu's nu este nevoie să se aplice "aplică". =)
EDIT
Tu ar trebui să ia, de asemenea, o privire la "norma" pachetului. Ea are o mulțime de caracteristici frumos pentru lipsă de analiză a datelor. =)
La dplyr hibridizat opțiuni sunt acum în jur de 30% mai rapid decât Baza R subset reassigns. Pe 100M datapoint dataframe mutate_all(~înlocui(., este.na(.), 0))
execută o jumătate de secundă mai rapid decât baza R d[este.na(d)] <- 0
opțiune. Ceea ce vrea să evite în mod special este folosind un ifelse () " sau " if_else(). (Completă 600 proces de analiză a fugit la peste 4.5 ore în mare parte datorită inclusiv aceste abordări.) Vă rugăm să consultați referință analizele de mai jos pentru rezultate complete. Daca te confrunti cu masive dataframes,
de date.masa` este cea mai rapidă opțiune de toate: cu 40% mai rapid decât standard de Baza R abordare. Se modifică, de asemenea, datele din loc, în mod eficient, permițându-vă pentru a lucra cu aproape de două ori la fel de mult de date la o dată.
Locationally:
mutate_at(c(5:10), ~înlocui(., este.na(.), 0))
mutate_at(vars(var5:var10), ~înlocui(., este.na(.), 0))
mutate_at(vars(conține("1")), ~înlocui(., este.na(.), 0))
conține()
, încerc ends_with()
,starts_with()
mutate_at(vars(meciuri("\\d{2}")), ~înlocui(., este.na(.), 0))
Condițional:
(se schimba doar numeric (coloane) și se lasă string (coloane) singur.) mutate_if(este.integer, ~înlocui(., este.na(.), 0))
mutate_if(este.numeric, ~înlocui(., este.na(.), 0))
mutate_if(este.caracter, ~înlocui(., este.na(.), 0))
Actualizat pentru dplyr 0.8.0: folosirea funcțiilor purrr format ~
simboluri: înlocuirea depreciat iubitori()
argumente.
# 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.fnafill <- function(x) { fnafill(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) Unitate: milisecunde 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 josnice.sbst.rssgn 1480.5098 1686.1581 1730.006 1728.477 1772.951 2010.215 600 josnice.înlocuiți 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.înlocuiți 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 josnice.pentru 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.pentru.set.nms 761.6086 915.8166 1015.457 1001.772 1106.315 1363.044 600 DT.pentru.set.sqln 787.3535 918.8733 1017.812 1002.042 1122.474 1321.860 600
Boxplot de Rezultate
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)))
Atunci când seturi de date mari, Tidyr''s replace_na
a avut istoric scos în față. Cu actuala colecție de 100 de milioane de puncte de date pentru a rula prin intermediul, se efectuează aproape exact la fel de bine ca o Baza R Pentru Buclă. Sunt curios să văd ce se întâmplă pentru diferite dimensiuni dataframes.
Exemple suplimentare pentru evolua
și rezum
`_at " și " _all funcția variante pot fi găsite aici: https://rdrr.io/cran/dplyr/man/summarise_all.html
În plus, am găsit util demonstrații și colecții de exemple aici: https://blog.exploratory.io/dplyr-0-5-is-awesome-heres-why-be095fd4eb8a
Cu mulțumiri speciale pentru:
coaguleze()
funcția și actualizarea analizei. Pentru un singur vector:
x <- c(1,2,NA,4,5)
x[is.na(x)] <- 0
Pentru un date.cadru, face o funcție de mai sus, apoi "apply" la coloane.
Vă rugăm să furnizați o reproductibile exemplu data viitoare cum este detaliat aici:
https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example
dplyr exemplu:
library(dplyr)
df1 <- df1 %>%
mutate(myCol1 = if_else(is.na(myCol1), 0, myCol1))
Notă: Aceasta funcționează pe coloană selectată, dacă avem nevoie pentru a face acest lucru pentru toată coloana, vezi @reidjax's a răspunde folosind mutate_each.
Știu că întrebarea este deja răspuns, dar procedând în acest fel ar putea fi mai util pentru unii:
Defini această funcție:
na.zero <- function (x) {
x[is.na(x)] <- 0
return(x)
}
Acum ori de câte ori aveți nevoie pentru a converti NA's într-un vector de la zero's se poate face:
na.zero(some.vector)
Cu dplyr0.5.0, puteți utiliza
coaguleze funcția care pot fi integrate cu ușurință în %>%
conducta de a face coaguleze(vec, 0)
. Acesta înlocuiește toate NAs în vec
cu 0:
Spunem că avem un cadru de date cu `NA lui:
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
Abordare mai generală de utilizare a înlocui()` în matrice sau vector pentru a înlocui " NA " la "0"
De exemplu:
> x <- c(1,2,NA,NA,1,1)
> x1 <- replace(x,is.na(x),0)
> x1
[1] 1 2 0 0 1 1
Acest lucru este, de asemenea, o alternativă la utilizarea ifelse () " în " dplyr
df = data.frame(col = c(1,2,NA,NA,1,1))
df <- df %>%
mutate(col = replace(col,is.na(col),0))
Dacă doriți să înlocuiți NAs în factor de variabile, acest lucru ar putea fi utile:
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")
Acesta transformă un factor-vector într-un vector numeric și adaugă un alt artificiale factor numeric nivel, care este apoi transformat înapoi la un factor-vector cu un extra "NA-nivel" de alegerea ta.
Ar'am comentat pe @ianmunoz's de post, dar nu't au suficient de reputație. Puteți combina dplyr
's mutate_each
și "înlocuiți" pentru a avea grijă de " NA " a 0
înlocuire. Folosind dataframe de la @aL3xa's a raspuns...
> 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
Am're folosind standard de evaluare (SE) aici care este motivul pentru care avem nevoie de subliniere pe "funs_
." Avem, de asemenea, folosi lazyeval
's interp
/~
și .
referințe "tot ceea ce suntem de lucru cu", adică cadru de date. Acum sunt zero!
Un alt dplyrconducta compatibil opțiune cu tidyr'method
replace_na` care lucrează pentru mai multe coloane:
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)
Puteți cu ușurință să limiteze, de exemplu numeric coloane:
d$str <- c("string", NA)
myList <- myList[sapply(d, is.numeric)]
df <- d %>% replace_na(myList)
Dedicat funcția (nafill
/ setnafill
) pentru acest scop este în ultimii date.tabelul` versiune
r instala.pachete("de date.masa", repo="https://Rdatatable.gitlab.io/data.table") biblioteca(date.tabelul) ans_df = nafill(df, umple=0) setnafill(df, umple=0) # aceasta actualizează în loc
Această funcție simplă extras din Datacamp ar putea ajuta:
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
}
Apoi
replace_missings(df, replacement = 0)