แทนที่ค่า 0 ทั้งหมดเป็น NA


145

ฉันมี dataframe พร้อมคอลัมน์ตัวเลขบางตัว บางแถวมีค่า 0 ซึ่งควรพิจารณาว่าเป็นโมฆะในการวิเคราะห์ทางสถิติ วิธีที่เร็วที่สุดในการแทนที่ค่า 0 ทั้งหมดเป็น NULL ใน R คืออะไร


17
ฉันไม่คิดว่าคุณต้องการ / สามารถแทนที่ด้วยค่า NULL แต่ NA ให้บริการวัตถุประสงค์ใน R lingo
ไล่

คำตอบ:


244

แทนที่ศูนย์ทั้งหมดเป็น NA:

df[df == 0] <- NA



คำอธิบาย

1.ไม่ใช่NULLสิ่งที่คุณควรต้องการแทนที่ศูนย์ด้วย ตามที่กล่าวใน?'NULL',

NULL แสดงถึงวัตถุ null ใน R

ซึ่งเป็นเอกลักษณ์และฉันคิดว่าสามารถมองได้ว่าเป็นวัตถุที่ไม่รู้เรื่องและว่างเปล่าที่สุด 1จากนั้นไม่น่าแปลกใจเลยที่

data.frame(x = c(1, NULL, 2))
#   x
# 1 1
# 2 2

นั่นคือ R ไม่ได้จองพื้นที่ใด ๆ สำหรับวัตถุ null นี้ 2ในขณะเดียวกันดูที่?'NA'เราเห็นว่า

NA เป็นค่าคงที่เชิงตรรกะของความยาว 1 ซึ่งมีตัวบ่งชี้ค่าที่ขาดหายไป NA สามารถ coerced กับเวกเตอร์ชนิดอื่นยกเว้น raw

ที่สำคัญNAมีความยาว 1 เพื่อให้ R สงวนพื้นที่ไว้ให้ เช่น,

data.frame(x = c(1, NA, 2))
#    x
# 1  1
# 2 NA
# 3  2

นอกจากนี้โครงสร้างเฟรมข้อมูลต้องการคอลัมน์ทั้งหมดเพื่อให้มีองค์ประกอบจำนวนเดียวกันเพื่อที่จะไม่มี "รู" (เช่นNULLค่า)

ตอนนี้คุณสามารถแทนที่ศูนย์ด้วยNULLในกรอบข้อมูลในแง่ของการลบแถวทั้งหมดที่มีอย่างน้อยหนึ่งศูนย์ เมื่อใช้เช่นvar, covหรือcorที่เป็นจริงเทียบเท่ากับครั้งแรกของการเปลี่ยนเลขด้วยNAและการตั้งค่าของการเป็นuse "complete.obs"อย่างไรก็ตามโดยทั่วไปสิ่งนี้ไม่เป็นที่น่าพอใจเนื่องจากนำไปสู่การสูญเสียข้อมูลเพิ่มเติม

2.แทนที่จะใช้ลูปบางประเภทในโซลูชันฉันใช้df == 0vectorization df == 0ผลตอบแทน (ลอง) เมทริกซ์ที่มีขนาดเดียวกับdfที่มีรายการและTRUE FALSEนอกจากนี้เรายังได้รับอนุญาตให้ส่งเมทริกซ์นี้ไปยังการตั้งค่าย่อย[...](ดู?'[') สุดท้ายในขณะที่ผลลัพธ์ของการdf[df == 0]ใช้งานง่ายอย่างสมบูรณ์แบบมันอาจดูแปลกที่df[df == 0] <- NAให้ผลที่ต้องการ ผู้ประกอบการที่ได้รับมอบหมาย<-ไม่ได้ฉลาดเสมอไปและไม่สามารถใช้วิธีนี้กับวัตถุอื่น ๆ ได้ แต่จะทำเช่นนั้นกับ data frames เห็น?'<-'ไหม


1เซตว่างในทฤษฎีเซตรู้สึกว่าเกี่ยวข้องกัน
2ความคล้ายคลึงกันอื่น ๆ กับทฤษฎีเซต: เซตว่างเป็นเซตย่อยของทุกเซต แต่เราจะไม่สงวนพื้นที่ใด ๆ ไว้


3
สิ่งที่จะเทียบเท่าไวยากรณ์สำหรับวัตถุ data.table?
itpetersen

6
ฉันเห็นว่าคุณได้รับการโหวตจำนวนมาก แต่อย่าคิดว่าสิ่งนี้จะครอบคลุมกรณีขอบของคอลัมน์ที่ไม่ใช่ตัวเลขอย่างเหมาะสมด้วยค่า "0" ซึ่งไม่ได้ขอให้ตั้งค่าเป็น <NA>
IRTFM

33

ให้ฉันสมมติว่า data.frame ของคุณเป็นการผสมผสานของประเภทข้อมูลที่แตกต่างกันและไม่จำเป็นต้องแก้ไขคอลัมน์ทั้งหมด

หากต้องการแก้ไขเฉพาะคอลัมน์ 12 ถึง 18 (จากทั้งหมด 21) ให้ทำเช่นนี้

df[, 12:18][df[, 12:18] == 0] <- NA

สิ่งนี้ใช้ได้กับฉันในขณะที่คำตอบที่ยอมรับไม่ได้
Patrick Coulombe

23

ทางเลือกอื่นที่ไม่มี[<-ฟังก์ชัน:

กรอบข้อมูลตัวอย่างdat(คัดลอกมาจากคำตอบของ @ Chase):

dat

  x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0

เลขสามารถถูกแทนที่ด้วยNAโดยis.na<-ฟังก์ชั่น:

is.na(dat) <- !dat


dat

   x  y
1 NA  2
2  1  2
3  1  1
4  2  1
5 NA NA

22

dplyr::na_if() เป็นตัวเลือก:

library(dplyr)  

df <- data_frame(col1 = c(1, 2, 3, 0),
                 col2 = c(0, 2, 3, 4),
                 col3 = c(1, 0, 3, 0),
                 col4 = c('a', 'b', 'c', 'd'))

na_if(df, 0)
# A tibble: 4 x 4
   col1  col2  col3 col4 
  <dbl> <dbl> <dbl> <chr>
1     1    NA     1 a    
2     2     2    NA b    
3     3     3     3 c    
4    NA     4    NA d


12

เนื่องจากมีคนถามหา Data.Table เวอร์ชันนี้และเนื่องจากโซลูชัน data.frame ที่กำหนดไม่สามารถใช้งานกับ data.table ได้ฉันจึงนำเสนอโซลูชันด้านล่าง

โดยทั่วไปให้ใช้:=โอเปอเรเตอร์ ->DT[x == 0, x := NA]

library("data.table")

status = as.data.table(occupationalStatus)

head(status, 10)
    origin destination  N
 1:      1           1 50
 2:      2           1 16
 3:      3           1 12
 4:      4           1 11
 5:      5           1  2
 6:      6           1 12
 7:      7           1  0
 8:      8           1  0
 9:      1           2 19
10:      2           2 40


status[N == 0, N := NA]

head(status, 10)
    origin destination  N
 1:      1           1 50
 2:      2           1 16
 3:      3           1 12
 4:      4           1 11
 5:      5           1  2
 6:      6           1 12
 7:      7           1 NA
 8:      8           1 NA
 9:      1           2 19
10:      2           2 40

2
for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA)หรือ ดูที่นี่สำหรับการสนทนาโดยละเอียดเพิ่มเติมเกี่ยวกับการใช้ data.table เพื่อค้นหาและแทนที่ค่า
JWilliman

4

คุณสามารถแทนที่ได้0ด้วยNAในเขตข้อมูลตัวเลขเท่านั้น (เช่นไม่รวมสิ่งต่าง ๆ เช่นปัจจัย) แต่ทำงานได้ในแต่ละคอลัมน์:

col[col == 0 & is.numeric(col)] <- NA

ด้วยฟังก์ชั่นคุณสามารถใช้สิ่งนี้กับกรอบข้อมูลทั้งหมดของคุณ:

changetoNA <- function(colnum,df) {
    col <- df[,colnum]
    if (is.numeric(col)) {  #edit: verifying column is numeric
        col[col == -1 & is.numeric(col)] <- NA
    }
    return(col)
}
df <- data.frame(sapply(1:5, changetoNA, df))

แม้ว่าคุณจะสามารถแทนที่ด้วยหมายเลขของคอลัมน์ในกรอบข้อมูลของคุณหรือ1:51:ncol(df)


ฉันไม่แน่ใจว่านี่เป็นทางออกที่ถูกต้อง แล้วคอลัมน์ 6 ขึ้นไปล่ะ พวกเขาจะถูกตัด
userJT

นั่นเป็นเหตุผลที่ฉันแนะนำให้แทนที่1:5ด้วย1:ncol(df)ในตอนท้าย ฉันไม่ต้องการสร้างสมการที่ซับซ้อนเกินไปหรืออ่านยาก
Alium Britt

แต่จะเกิดอะไรขึ้นถ้าในคอลัมน์ 6 และ 7 - ประเภทข้อมูลเป็นอักขระถ่านและไม่ควรทำการแทนที่ ในปัญหาของฉันฉันต้องเปลี่ยนเฉพาะในคอลัมน์ 12 ถึง 15 แต่ df ทั้งหมดมี 21 คอลัมน์ (หลายคนต้องไม่แตะเลย)
userJT

สำหรับกรอบข้อมูลของคุณคุณก็สามารถเปลี่ยน1:5ไปยังหมายเลขคอลัมน์ที่คุณต้องการเปลี่ยนแปลงเช่นแต่ถ้าคุณอยากจะยืนยันว่ามันจะมีผลเฉพาะคอลัมน์ที่เป็นตัวเลขแล้วก็ตัดบรรทัดที่สองของฟังก์ชั่นในงบถ้าเช่นนี้12:15 if (is.numeric(col)) { col[col == -1 & is.numeric(col)] <- NA }
Alium Britt

0

ในกรณีที่ใครมาถึงที่นี่ผ่านทาง google มองหาสิ่งที่ตรงกันข้าม (เช่นวิธีการแทนที่ NAs ทั้งหมดใน data.frame ด้วย 0) คำตอบคือ

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

หรือ

ใช้ dplyr / tidyverse

library(dplyr)
mtcars %>% replace(is.na(.), 0)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.