Saya memiliki data frame dan beberapa kolom memiliki NA
nilai-nilai.
Bagaimana cara mengganti ini NA
dengan nilai nol?
Lihat komentar saya di @gsk3 menjawab. Contoh sederhana:
> 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
Ada's tidak perlu menerapkan terapkan
. =)
EDIT
Anda juga harus melihat pada norma
paket. Ini memiliki banyak fitur yang bagus untuk hilang analisis data. =)
Yang dplyr hibridisasi pilihan sekarang sekitar 30% lebih cepat dari Basis R subset reassigns. Pada 100M datapoint dataframe mutate_all(~menggantikan(., adalah.na(.), 0))
berjalan setengah detik lebih cepat dari basis R d[ini.na(d)] <- 0
pilihan. Apa yang ingin menghindari khusus adalah menggunakan ifelse()
atau if_else()
. (Lengkap 600 percobaan analisis berlari ke lebih dari 4,5 jam sebagian besar karena termasuk pendekatan ini.) Silahkan lihat acuan analisis di bawah ini untuk menyelesaikan hasil.
Jika anda sedang berjuang dengan besar dataframes, data.meja
adalah pilihan tercepat dari semua: 40% lebih cepat dari standar Basis R pendekatan. Hal ini juga memodifikasi data di tempat, secara efektif memungkinkan anda untuk bekerja dengan hampir dua kali lebih banyak data sekaligus.
Locationally:
mutate_at(c(5:10), ~menggantikan(., adalah.na(.), 0))
mutate_at(vars(var5:var10), ~menggantikan(., adalah.na(.), 0))
mutate_at(vars(mengandung("1")), ~menggantikan(., adalah.na(.), 0))
berisi()
, mencoba ends_with()
,starts_with()
mutate_at(vars(pertandingan("\\d{2}")), ~menggantikan(., adalah.na(.), 0))
Persyaratan:
(perubahan hanya numerik (kolom) dan meninggalkan string (kolom) saja.) mutate_if(adalah.integer, ~menggantikan(., adalah.na(.), 0))
mutate_if(adalah.numerik, ~menggantikan(., adalah.na(.), 0))
mutate_if(adalah.karakter, ~menggantikan(., adalah.na(.), 0))
Diperbarui untuk dplyr 0.8.0: fungsi menggunakan purrr format ~
simbol: mengganti usang funs()
argumen.
# 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) Unit: milidetik penglm min lq berarti rata-rata 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.mengganti 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.mengganti 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.untuk 869.3169 1180.8311 1216.958 1224.407 1264.737 1459.726 600 hybrd.rplc_at.bei 839.8915 1189.7465 1223.326 1228.329 1266.375 1565.794 600 DT.untuk.set.nms 761.6086 915.8166 1015.457 1001.772 1106.315 1363.044 600 DT.untuk.set.sqln 787.3535 918.8733 1017.812 1002.042 1122.474 1321.860 600
Boxplot dari Hasil
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)))
Ketika dataset mendapatkan yang lebih besar, Tidyr''s replace_na
secara historis ditarik keluar di depan. Dengan koleksi 100 poin data untuk menjalankan melalui, ia melakukan hampir persis serta Basis R Untuk Loop. Saya penasaran untuk melihat apa yang terjadi untuk ukuran yang berbeda dataframes.
Contoh-contoh tambahan untuk bermutasi
dan meringkas
_at
dan semu_a
fungsi varian dapat ditemukan di sini: https://rdrr.io/cran/dplyr/man/summarise_all.html
Selain itu, saya menemukan sangat membantu demonstrasi dan koleksi dari contoh-contoh berikut ini: https://blog.exploratory.io/dplyr-0-5-is-awesome-heres-why-be095fd4eb8a
Khusus terima kasih kepada:
lokal()
, dan (dengan Frank's pasien membantu juga) peran yang diam paksaan berperan dalam mempercepat banyak dari pendekatan ini. menyatu()
fungsi dan update analisis. data.tabel
fungsi cukup baik untuk akhirnya memasukkan mereka dalam lineup. Untuk satu vektor:
x <- c(1,2,NA,4,5)
x[is.na(x)] <- 0
Untuk data.bingkai, membuat fungsi di atas, maka apply
untuk kolom.
Mohon memberikan direproduksi contoh waktu berikutnya rinci sebagai berikut:
https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example
dplyr contoh:
library(dplyr)
df1 <- df1 %>%
mutate(myCol1 = if_else(is.na(myCol1), 0, myCol1))
Catatan: Ini bekerja per kolom yang dipilih, jika perlu kita lakukan ini untuk semua kolom, lihat @reidjax's jawaban dengan menggunakan mutate_each.
Aku tahu pertanyaan ini sudah dijawab, tapi melakukannya dengan cara ini mungkin akan lebih berguna untuk beberapa:
Menentukan fungsi ini:
na.zero <- function (x) {
x[is.na(x)] <- 0
return(x)
}
Sekarang setiap kali anda perlu mengkonversi NA's dalam vektor nol's yang dapat anda lakukan:
na.zero(some.vector)
Dengan dplyr
0.5.0, anda dapat menggunakan menyatu
fungsi yang dapat dengan mudah diintegrasikan ke %>%
pipa dengan melakukan menyatu(vec, 0)
. Ini menggantikan semua NAs di vec
dengan 0:
Katakanlah kita memiliki sebuah data frame dengan `NA:
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
Lebih umum pendekatan menggunakan ganti()
dalam matriks atau vektor untuk menggantikan NA
ke 0
Misalnya:
> x <- c(1,2,NA,NA,1,1)
> x1 <- replace(x,is.na(x),0)
> x1
[1] 1 2 0 0 1 1
Ini juga merupakan alternatif untuk menggunakan ifelse()
di dplyr
df = data.frame(col = c(1,2,NA,NA,1,1))
df <- df %>%
mutate(col = replace(col,is.na(col),0))
Jika anda ingin mengganti NAs dalam faktor variabel, ini mungkin berguna:
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")
Ini mengubah faktor-vektor ke vektor numerik dan menambah satu lagi buatan numerik faktor tingkat, yang kemudian berubah kembali ke faktor-vektor dengan satu tambahan "NA-tingkat" pilihan anda.
Akan've mengomentari @ianmunoz's post tapi aku don't memiliki cukup reputasi. Anda dapat menggabungkan dplyr
's mutate_each
dan menggantikan
mengurus NA
ke 0
penggantian. Menggunakan dataframe dari @aL3xa's jawaban...
> 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
Kami're menggunakan standar evaluasi (SE) berikut ini yang adalah mengapa kita perlu menggarisbawahi pada "funs_
." Kami juga menggunakan lazyeval
's interp
/~
dan .
referensi "segala sesuatu yang kita bekerja dengan", yaitu data frame. Sekarang ada angka nol!
Lain dplyr
pipa opsi yang kompatibel dengan tidyr
metode ' replace_na` yang bekerja untuk beberapa kolom:
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)
Anda dapat dengan mudah membatasi misalnya untuk kolom numerik:
d$str <- c("string", NA)
myList <- myList[sapply(d, is.numeric)]
df <- d %>% replace_na(myList)
Fungsi khusus (nafill
/ setnafill
) untuk tujuan itu adalah dalam beberapa data.tabel
versi
r menginstal.paket("data.meja", repos="https://Rdatatable.gitlab.io/data.table") perpustakaan(data.tabel) ans_df = nafill(df, isi=0) setnafill(df, isi=0) # ini salah satu update di-tempat
Fungsi sederhana ini diekstrak dari Datacamp bisa membantu:
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
}
Kemudian
replace_missings(df, replacement = 0)
jika anda ingin menetapkan nama baru setelah mengubah NAs dalam sebuah kolom tertentu dalam hal ini kolom V3, menggunakan yang anda dapat lakukan juga seperti ini
my.data.frame$the.new.column.name <- ifelse(is.na(my.data.frame$V3),0,1)