ฉันจะแทนที่ค่า NA ด้วยค่าศูนย์ใน R dataframe ได้อย่างไร


727

ฉันมีกรอบข้อมูลและบางคอลัมน์มีNAค่า

ฉันจะแทนที่NAค่าเหล่านี้ด้วยศูนย์ได้อย่างไร


13
การปรับเปลี่ยนเล็กน้อยของstackoverflow.com/questions/7279089/… (ซึ่งฉันค้นพบโดยการค้นหา "[r] แทนที่ NA ด้วยศูนย์") ...
Ben Bolker

25
d [is.na (d)] <- 0
psychonomics

คำตอบ:


879

ดูความคิดเห็นของฉันในคำตอบ @ gsk3 ตัวอย่างง่ายๆ:

> 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

applyไม่มีความจำเป็นที่จะนำไปใช้เป็น =)

แก้ไข

คุณควรดูnormแพ็คเกจด้วย มีคุณสมบัติที่ดีมากมายสำหรับการวิเคราะห์ข้อมูลที่ขาดหายไป =)


2
ฉันลองใช้รหัสนี้เมื่อวานนี้ก่อนที่คุณจะโพสต์และไม่ทำงาน เพราะนี่ฉันโพสต์คำถาม แต่ฉันพยายามรู้และทำงานอย่างสมบูรณ์ ฉันคิดว่าฉันกำลังทำอะไรผิด
Renato Dinhani

12
@ RenatoDinhaniConceição: ถ้าคุณลองอะไรแล้วจะมีประโยชน์ในการแบ่งปันข้อมูลนั้นเมื่อคุณถามคำถาม ช่วยให้แคบลงว่าปัญหาอาจอยู่ที่ใด
Aaron ออกจาก Stack Overflow เมื่อ

2
d [is.na (d)] <- 0 ไม่สมเหตุสมผลสำหรับฉัน ดูเหมือนย้อนหลังไหม R ประมวลผลคำสั่งนี้อย่างไร
user798719

13
@ user798719 - "<-" เป็นโอเปอเรเตอร์การมอบหมายของ R และสามารถอ่านได้ว่า: ทำอะไรบางอย่างทางด้านขวามือแล้วกำหนดให้ตำแหน่ง / ชื่อทางด้านซ้าย ในกรณีนี้เราไม่ได้ทำอะไรเลย - แค่สร้างศูนย์ ด้านซ้ายกำลังพูดว่า: ดูที่วัตถุ d ในวัตถุ d (วงเล็บเหลี่ยม) ค้นหาองค์ประกอบทั้งหมดที่ส่งคืน TRUE (is.na (d) ส่งกลับตรรกะสำหรับแต่ละองค์ประกอบ) เมื่อพบแล้วให้แทนที่พวกเขา ("กำหนดพวกเขา") ด้วยค่า 0 สิ่งเหล่านี้จะทำให้ผู้ที่ไม่ได้เป็น NA ทั้งหมดเหมือนเดิมและแทนที่พวกเขาด้วยความหายไปเท่านั้น
Twitch_City

3
และ ... ถ้าคุณมีกรอบข้อมูลและต้องการใช้การแทนที่เฉพาะเวกเตอร์ nurmeric ที่เฉพาะเจาะจง (ปล่อยให้พูดว่า ... สตริงกับ NA):df[19:28][is.na(df[19:28])] <- 0
jtdoud

299

ตัวเลือกไฮบริด dplyr ตอนนี้เร็วขึ้นประมาณ 30% กว่าชุดย่อย Base R ที่กำหนดใหม่ ในดาต้าพอยต์ 100M ดาต้าพ้อยท์mutate_all(~replace(., is.na(.), 0))รันเร็วกว่าd[is.na(d)] <- 0ตัวเลือกพื้นฐาน R ครึ่งวินาที สิ่งที่ใครอยากจะหลีกเลี่ยงโดยเฉพาะมีการใช้หรือifelse() if_else()(การวิเคราะห์การทดลองทั้งหมด 600 ครั้งใช้เวลานานกว่า 4.5 ชั่วโมงส่วนใหญ่เนื่องจากรวมถึงวิธีการเหล่านี้) โปรดดูการวิเคราะห์เกณฑ์มาตรฐานด้านล่างเพื่อดูผลลัพธ์ที่สมบูรณ์

หากคุณกำลังดิ้นรนกับ dataframes ใหญ่data.tableเป็นตัวเลือกที่เร็วที่สุดของทั้งหมด: 40% เร็วกว่ามาตรฐานฐาน Rวิธี นอกจากนี้ยังแก้ไขข้อมูลในสถานที่ได้อย่างมีประสิทธิภาพช่วยให้คุณสามารถทำงานกับข้อมูลเกือบสองเท่าในครั้งเดียว


การจัดกลุ่มของวิธีการทดแทน tidyverse ที่เป็นประโยชน์อื่น ๆ

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()ลองends_with(),starts_with()
  • จับคู่รูปแบบ mutate_at(vars(matches("\\d{2}")), ~replace(., is.na(.), 0))

เงื่อนไข:
(เปลี่ยนเพียงประเภทเดียวและปล่อยให้อยู่คนเดียวประเภทอื่น ๆ )

  • จำนวนเต็ม 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: ฟังก์ชั่นใช้~สัญลักษณ์รูปแบบ purrr : แทนที่funs()อาร์กิวเมนต์ที่เลิกใช้แล้ว

วิธีการทดสอบ:

# 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

Boxplot ของผลลัพธ์

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

เปรียบเทียบ Boxplot ของเวลาที่ผ่านไป

Scatterplot ของ Trials ที่ใช้รหัสสี (พร้อมแกน y บนมาตราส่วนบันทึก)

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

Scatterplot ของทุกช่วงเวลาทดลอง

หมายเหตุเกี่ยวกับนักแสดงสูงคนอื่น ๆ

เมื่อชุดข้อมูลขนาดใหญ่ได้รับ, Tidyr '' s replace_naได้ดึงอดีตออกไปข้างหน้า ด้วยการรวบรวมจุดข้อมูล 100M ปัจจุบันเพื่อให้ทำงานได้อย่างมีประสิทธิภาพเช่นเดียวกับBase R For Loop ฉันอยากรู้ว่าจะเกิดอะไรขึ้นกับดาต้าเฟรมขนาดต่าง ๆ

ตัวอย่างเพิ่มเติมสำหรับmutateและsummarize _atและ_allสายพันธุ์ที่ฟังก์ชั่นที่สามารถพบได้ที่นี่: https://rdrr.io/cran/dplyr/man/summarise_all.html นอกจากนี้ผมพบว่าการชุมนุมประท้วงที่เป็นประโยชน์และคอลเลกชันของตัวอย่างที่นี่: https: //blog.exploratory io / dplyr-0-5-เป็นน่ากลัวริ-ทำไม-be095fd4eb8a

คุณสมบัติและชื่นชม

ขอขอบคุณเป็นพิเศษกับ:

  • Tyler RinkerและAkrunสำหรับแสดงให้เห็นถึง microbenchmark
  • alexis_lazสำหรับการทำงานเพื่อช่วยให้ฉันเข้าใจการใช้งานlocal()และ (ด้วยความช่วยเหลือจากผู้ป่วยของแฟรงค์ด้วย) บทบาทที่การบังคับขู่เข็ญเงียบช่วยเร่งวิธีการเหล่านี้หลายวิธี
  • ArthurYip สำหรับการกระตุ้นเพื่อเพิ่มcoalesce()ฟังก์ชั่นใหม่ในและปรับปรุงการวิเคราะห์
  • Gregor สำหรับคนเขยิบหาdata.tableฟังก์ชั่นที่ดีพอที่จะรวมไว้ในรายการ
  • Base R For loop: alexis_laz
  • data.tableสำหรับลูป: Matt_Dowle
  • โรมันเพื่ออธิบายสิ่งที่is.numeric()ทดสอบจริง ๆ

(แน่นอนโปรดเอื้อมมือออกไปและให้พวกเขา upvotes เช่นกันหากคุณพบว่าวิธีการเหล่านั้นมีประโยชน์)

หมายเหตุเกี่ยวกับการใช้งาน Numerics ของฉัน: หากคุณมีชุดข้อมูลจำนวนเต็มจริงฟังก์ชันทั้งหมดของคุณจะทำงานได้เร็วขึ้น โปรดดูข้อมูลเพิ่มเติมจากงานของ alexiz_laz IRL ฉันจำการเผชิญหน้าชุดข้อมูลที่มีจำนวนเต็มมากกว่า 10-15% ไม่ได้ดังนั้นฉันจึงรันการทดสอบเหล่านี้กับดาต้าเฟรมที่เป็นตัวเลขอย่างสมบูรณ์

ฮาร์ดแวร์ที่ใช้ 3.9 GHz CPU พร้อม RAM 24 GB


2
@ Frank - ขอบคุณสำหรับการค้นหาความแตกต่างนั้น ข้อมูลอ้างอิงทั้งหมดถูกลบล้างและผลลัพธ์ได้รับการรันใหม่ทั้งหมดในเครื่องเดียวและผ่านรายการใหม่
leerssej

โอเคขอบคุณ. นอกจากนี้ฉันคิดว่าdf1[j][is.na(df1[j])] = 0ผิดควรเป็นdf1[[j]][is.na(df1[[j]])] = 0
Frank

โอ้ตอนนี้ฉันเห็นว่าคุณเขียนมันสองครั้งแตกต่างกันในแต่ละมาตรฐาน อย่างไรก็ตามforLp_Sbstดูเหมือนจะไม่เป็นวิธีที่ทุกคนควรพิจารณาที่จะเข้าใกล้forLp_smplfSbst
แฟรงก์

1
@UweBlock - คำถามที่ยอดเยี่ยม: มันอนุญาตให้ฉันทำการเซ็ตย่อยการดำเนินการด้านซ้ายด้วยฟังก์ชั่นทั้งหมดที่ทำงานบนดาต้าเฟรมเดียวกันทั้งหมด เนื่องจากฉันต้องปิดล้อมรอบฟังก์ชั่นนั้นในชื่อวิทยาศาสตร์ [งานหนึ่งคุณมีงานเดียว!] ฉันห่อมันไว้รอบ ๆ พวกเขาทั้งหมดเพื่อให้สนามเด็กเล่นอยู่ในระดับที่แจ่มแจ้ง สำหรับข้อมูลเพิ่มเติม - โปรดดูที่นี่: stackoverflow.com/questions/41604711/…ฉันได้ตัดทอนคำตอบก่อนหน้านี้ที่ค่อนข้างยาว - แต่ส่วนหนึ่งของการอภิปรายจะเป็นการดีที่จะเพิ่มกลับเข้ามาขอขอบคุณ!
leerssej

1
@ArthurYip - ฉันได้เพิ่มcoalesce()ตัวเลือกในและรันใหม่ตลอดเวลา ขอบคุณสำหรับเขยิบที่จะอัปเดต
leerssej

128

สำหรับเวกเตอร์เดียว:

x <- c(1,2,NA,4,5)
x[is.na(x)] <- 0

สำหรับ data.frame ให้สร้างฟังก์ชันจากด้านบนจากนั้นapplyไปยังคอลัมน์

โปรดให้ตัวอย่างที่ทำซ้ำได้ในครั้งต่อไปตามรายละเอียดที่นี่:

วิธีทำตัวอย่าง R ที่สามารถทำซ้ำได้อย่างยอดเยี่ยม


18
is.naเป็นฟังก์ชั่นทั่วไปและมีวิธีการสำหรับวัตถุของdata.frameชั้นเรียน ดังนั้นอันนี้ก็จะทำงานบนdata.frames!
aL3xa

3
เมื่อฉันวิ่งmethods(is.na)เป็นครั้งแรกฉันเหมือนwhaaa?!? . ฉันรักเมื่อสิ่งนั้นเกิดขึ้น! =)
aL3xa

9
สมมติว่าคุณมี data data ชื่อ df แทนที่จะเป็น vector เดียวและคุณต้องการแทนที่การสังเกตที่หายไปในคอลัมน์เดียวชื่อ X3 คุณสามารถทำได้ด้วยบรรทัดนี้: df $ X3 [is.na (df $ X3)] <- 0
Mark Miller

8
สมมติว่าคุณต้องการแทนที่ NA ด้วย 0 ในคอลัมน์ 4-6 ของเฟรมข้อมูลชื่อ my.df คุณสามารถใช้: my.df [, 4: 6] [is.na (my.df [, 4: 6])] <- 0
Mark Miller

ทำไมคุณถึงส่ง 'x' ไปยัง is.na (x) มีวิธีที่จะบอกว่าไลบรารีรูทีนใน R เป็นเวกเตอร์อย่างไร
uh_big_mike_boi

73

ตัวอย่าง dplyr:

library(dplyr)

df1 <- df1 %>%
    mutate(myCol1 = if_else(is.na(myCol1), 0, myCol1))

หมายเหตุ:ผลงานต่อคอลัมน์ที่เลือกนี้ถ้าเราจำเป็นต้องทำเช่นนี้สำหรับคอลัมน์ทั้งหมดให้ดู@reidjax 's คำตอบโดยใช้mutate_each


57

หากเราพยายามแทนที่NAs เมื่อส่งออกเช่นเมื่อเขียนถึง csv เราสามารถใช้:

  write.csv(data, "data.csv", na = "0")

47

ฉันรู้ว่าคำถามได้รับคำตอบแล้ว แต่การทำเช่นนี้อาจมีประโยชน์มากกว่าสำหรับบางคน:

กำหนดฟังก์ชั่นนี้:

na.zero <- function (x) {
    x[is.na(x)] <- 0
    return(x)
}

ตอนนี้เมื่อใดก็ตามที่คุณต้องการแปลง NA ในเวกเตอร์เป็นศูนย์คุณสามารถทำได้:

na.zero(some.vector)

22

ด้วยdplyr0.5.0 คุณสามารถใช้coalesceฟังก์ชันที่สามารถรวมเข้ากับ%>%ไปป์ไลน์ได้โดยcoalesce(vec, 0)ง่าย สิ่งนี้จะแทนที่ NAs ทั้งหมดvecด้วย 0:

สมมติว่าเรามี data frame พร้อมNAs:

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

ฉันทดสอบรวมกันและมันทำงานคล้ายกับการแทนที่ คำสั่ง coalesce นั้นง่ายที่สุด!
Arthur Yip

มันจะมีประโยชน์ถ้าคุณจะนำเสนอวิธีการที่นำไปใช้กับคอลัมน์ทั้งหมดของ 2 + คอลัมน์ tibble
jangorecki

21

วิธีการทั่วไปอื่น ๆ ของการใช้replace()ในเมทริกซ์หรือเวกเตอร์ที่จะเปลี่ยนNAไป0

ตัวอย่างเช่น:

> x <- c(1,2,NA,NA,1,1)
> x1 <- replace(x,is.na(x),0)
> x1
[1] 1 2 0 0 1 1

นี่เป็นอีกทางเลือกifelse()ในการใช้งานdplyr

df = data.frame(col = c(1,2,NA,NA,1,1))
df <- df %>%
   mutate(col = replace(col,is.na(col),0))

1
คอลัมน์ของฉันเป็นปัจจัยดังนั้นฉันจึงต้องเพิ่มค่าทดแทนของฉันlevels(A$x) <- append(levels(A$x), "notAnswered") A$x <- replace(A$x,which(is.na(A$x)),"notAnswered")
Climbs_lika_Spyder

1
whichx1 <- replace(x,is.na(x),1)ไม่จำเป็นต้องที่นี่คุณสามารถใช้
lmo

ฉันพยายามหลายวิธีที่นำเสนอในหัวข้อนี้เพื่อแทนที่NAไป0ในเวลาเพียงหนึ่งคอลัมน์ที่ระบุในกรอบข้อมูลขนาดใหญ่และฟังก์ชั่นนี้replace()ทำงานได้อย่างมีประสิทธิภาพมากที่สุดในขณะนี้ยังมีส่วนใหญ่ก็
Duc

19

tidyr::replace_naนอกจากนี้ยังเป็นไปได้ที่จะใช้

    library(tidyr)
    df <- df %>% mutate_all(funs(replace_na(.,0)))


9

หากคุณต้องการแทนที่ NAs ในตัวแปรปัจจัยสิ่งนี้อาจมีประโยชน์:

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

มันจะแปลงแฟคเตอร์แบบเวกเตอร์เป็นเวกเตอร์ตัวเลขและเพิ่มอีกหนึ่งระดับตัวเลขเชิงประดิษฐ์ซึ่งจะถูกแปลงกลับไปเป็นแฟคเตอร์แบบเวกเตอร์พร้อมระดับ "NA-level" พิเศษที่คุณเลือก


8

จะแสดงความคิดเห็นในโพสต์ของ @ ianmunoz แต่ฉันไม่มีชื่อเสียงเพียงพอ คุณสามารถรวมdplyr 's mutate_eachและreplaceการดูแลของNAการ0ทดแทน กำลังใช้งาน dataframe จากคำตอบของ @ aL3xa ...

> 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

เรากำลังใช้การประเมินมาตรฐาน (SE) ที่นี่ซึ่งเป็นสาเหตุที่เราต้องการขีดล่างบน " funs_" นอกจากนี้เรายังใช้lazyeval's interp/ ~และ.อ้างอิง "ทุกสิ่งที่เราทำงานด้วย" เช่นกรอบข้อมูล ตอนนี้มีศูนย์!


4

คุณสามารถใช้ได้ replace()

ตัวอย่างเช่น:

> 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

6
จริง แต่ใช้ได้จริงเมื่อคุณรู้ดัชนีของNAs ในเวกเตอร์ของคุณ มันดีสำหรับเวกเตอร์ตัวเล็ก ๆ ดังตัวอย่างของคุณ
dardisco

4
@dardisco x1 <- replace(x,is.na(x),1)จะทำงานโดยไม่แสดงรายการค่าดัชนีอย่างชัดเจน
lmo

4

dplyrตัวเลือกที่เข้ากันได้กับไปป์อื่นด้วย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)

คุณสามารถ จำกัด เช่นคอลัมน์ตัวเลขได้อย่างง่ายดาย:

d$str <- c("string", NA)

myList <- myList[sapply(d, is.numeric)]

df <- d %>% replace_na(myList)

4

ฟังก์ชันเฉพาะ ( nafill/ setnafill) สำหรับจุดประสงค์นั้นอยู่ในdata.tableรุ่นล่าสุด

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

สำหรับผู้ที่กำลังลงคะแนนเสียงโปรดให้ข้อเสนอแนะเช่นกันเพื่อให้คำตอบของฉันสามารถปรับปรุงได้
jangorecki

3

ฟังก์ชั่นที่เรียบง่ายนี้สกัดจากDatacampสามารถช่วย:

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
}

แล้วก็

replace_missings(df, replacement = 0)

3

วิธีง่ายๆในการเขียนนั้นif_naมาจากhablar:

library(dplyr)
library(hablar)

df <- tibble(a = c(1, 2, 3, NA, 5, 6, 8))

df %>% 
  mutate(a = if_na(a, 0))

ซึ่งผลตอบแทน:

      a
  <dbl>
1     1
2     2
3     3
4     0
5     5
6     6
7     8


1

หากคุณต้องการกำหนดชื่อใหม่หลังจากเปลี่ยน NAs ในคอลัมน์ที่ระบุในคอลัมน์กรณีนี้ V3 ให้ใช้คุณสามารถทำเช่นนี้ได้

my.data.frame$the.new.column.name <- ifelse(is.na(my.data.frame$V3),0,1)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.