
在數(shù)據(jù)分析中,有時候需要將缺失數(shù)據(jù)進(jìn)行刪除。刪除數(shù)據(jù)很有講究,比如多性狀模型分析時,個體ID1的y1性狀缺失,y2性狀不缺失,評估y1時,不僅可以通過親緣關(guān)系矩陣和固定因子進(jìn)行評估,還可以根據(jù)y1和y2的遺傳相關(guān)進(jìn)行評估,這時候,y1的缺失就不需要刪除。
有時候y1和y2性狀都缺失,這時候就沒有必要保留了,增加運算量,還增加錯誤的可能性,這時候就需要將其刪除。
一般都是使用tidyverse進(jìn)行清洗數(shù)據(jù),但是drop_na函數(shù)沒有這個功能,這里總結(jié)一下,如果有這種需求,如何處理。 tidyverse的drop_na 函數(shù),當(dāng)面對多個列時,它的選擇是“或”,即是只有有有一列有缺失,都刪掉。有時候我們想將兩列都為缺失的刪掉,如果只有一列有缺失,要保留。 舉個例子: 「示例數(shù)據(jù):」 set.seed(123) dat = data.frame(ID = 1:10,y1 = c(NA,NA,1.05,NA,rnorm(6)), y2 = c(1,NA,NA,NA,rnorm(6))) dat
> dat ID y1 y2 1 1 NA 1.0000000 2 2 NA NA 3 3 1.05000000 NA 4 4 NA NA 5 5 -0.56047565 0.4609162 6 6 -0.23017749 -1.2650612 7 7 1.55870831 -0.6868529 8 8 0.07050839 -0.4456620 9 9 0.12928774 1.2240818 10 10 1.71506499 0.3598138
這個數(shù)據(jù)中: 1. 把y1缺失的刪掉> # 去掉y1缺失的行 > dat %>% drop_na(y1) ID y1 y2 1 3 1.05000000 NA 2 5 -0.56047565 0.4609162 3 6 -0.23017749 -1.2650612 4 7 1.55870831 -0.6868529 5 8 0.07050839 -0.4456620 6 9 0.12928774 1.2240818 7 10 1.71506499 0.3598138
可以看到,1,2,4行被刪掉了 2. 把y2缺失的刪掉> # 去掉y2缺失的行 > dat %>% drop_na(y2) ID y1 y2 1 1 NA 1.0000000 2 5 -0.56047565 0.4609162 3 6 -0.23017749 -1.2650612 4 7 1.55870831 -0.6868529 5 8 0.07050839 -0.4456620 6 9 0.12928774 1.2240818 7 10 1.71506499 0.3598138
可以看到,2,3,4行被刪掉了 3. 把y1或者y2缺失的都刪掉> # 去掉y1或者y2缺失的行:1,2,3,4, > dat %>% drop_na(y1,y2) ID y1 y2 1 5 -0.56047565 0.4609162 2 6 -0.23017749 -1.2650612 3 7 1.55870831 -0.6868529 4 8 0.07050839 -0.4456620 5 9 0.12928774 1.2240818 6 10 1.71506499 0.3598138
可以看到,1,2,3,4行被刪掉了 上面都是常規(guī)操作,drop_na完全沒問題。但是我想把y1和y2同時缺失的行刪掉,這個就不太好辦了。drop_na好像沒有相關(guān)的選項。 我看到一個issues:https://github.com/tidyverse/tidyr/issues/1054 想問hardey能不能增加這樣的參數(shù),有一個.logic參數(shù),默認(rèn)為or,可以設(shè)置and,但是hardy反手給另一個回答點贊了…… 「錯誤的代碼:」 penguins %>% drop_na(body_mass_g, sex, .logic = "AND")
「正確的代碼:」 palmerpenguins::penguins %>% filter(!across(c(body_mass_g, sex), .fns = is.na))
4. 把y1和y2缺失同時缺失的刪掉dat %>% filter(!(is.na(y1) & is.na(y2)))
> dat %>% filter(!(is.na(y1) & is.na(y2))) ID y1 y2 1 1 NA 1.0000000 2 3 1.05000000 NA 3 5 -0.56047565 0.4609162 4 6 -0.23017749 -1.2650612 5 7 1.55870831 -0.6868529 6 8 0.07050839 -0.4456620 7 9 0.12928774 1.2240818 8 10 1.71506499 0.3598138
可以看到,2,4行y1和y2都缺失,刪掉了。 另一種方法: dat %>% filter(!is.na(y1) | !is.na(y2))
> dat %>% filter(!(is.na(y1) & is.na(y2))) ID y1 y2 1 1 NA 1.0000000 2 3 1.05000000 NA 3 5 -0.56047565 0.4609162 4 6 -0.23017749 -1.2650612 5 7 1.55870831 -0.6868529 6 8 0.07050839 -0.4456620 7 9 0.12928774 1.2240818 8 10 1.71506499 0.3598138
還有一種,hardey贊同的方法: # 去掉y1和y2同時缺失的行:2,4 dat %>% filter(!across(c(y1,y2), .fns = is.na))
> dat %>% filter(!across(c(y1,y2), .fns = is.na)) ID y1 y2 1 3 1.05000000 NA 2 5 -0.56047565 0.4609162 3 6 -0.23017749 -1.2650612 4 7 1.55870831 -0.6868529 5 8 0.07050839 -0.4456620 6 9 0.12928774 1.2240818 7 10 1.71506499 0.3598138
方法看起來很復(fù)雜。還是我寫的比較簡單: # 去掉y1和y2同時缺失的行:2,4 dat %>% filter(!is.na(y1) | !is.na(y2))
dat %>% filter(!(is.na(y1) & is.na(y2)))
5. 所有測試代碼匯總set.seed(123) dat = data.frame(ID = 1:10,y1 = c(NA,NA,1.05,NA,rnorm(6)), y2 = c(1,NA,NA,NA,rnorm(6))) dat
## y1 缺失的行有:1,2,4 ## y2 缺失的行有:2,3,4 ## y1和y2都缺失的行有:2,4
library(tidyverse)
# 去掉y1缺失的行 dat %>% drop_na(y1)
# 去掉y2缺失的行 dat %>% drop_na(y2)
# 去掉y1或者y2缺失的行:1,2,3,4, dat %>% drop_na(y1,y2)
# 去掉y1和y2同時缺失的行:2,4 dat %>% filter(!is.na(y1) | !is.na(y2))
dat %>% filter(!(is.na(y1) & is.na(y2)))
# 去掉y1和y2同時缺失的行:2,4 dat %>% filter(!across(c(y1,y2), .fns = is.na))
|