2016-02-26 44 views
2

我有一個包含68列的數據幀。我想根據優先級排序的變量名稱向量來動態檢查無效數據。如果任何設置的字段是NA,我希望這些行移動到一個新的數據框中,該數據框會有一個包含排除原因的附加列。r從數據幀中動態刪除NA行並記錄哪個字段是不適用的

例如數據幀(只有5列):

df1=data.frame(id=c(1:6), 
    dob=as.Date(c("1/1/2001","2/2/2002",NA,"3/3/2003","1/1/1999",NA),"%m/%d/%Y"), 
    sex=c("F","F","M",NA,NA,"M"), 
    race=c("HA","HA","W","AA",NA,NA), 
    survey=c("1",NA,NA,NA,"1","0")) 

我希望能夠動態地定義required_cols。如果required_cols是:

required_cols<-c("sex","race") 

我想給所有行df1那有NA的性別和種族爲輸出表是這樣的移動:

id dob  sex race survey reason 
4 2003-03-03 <NA> AA <NA> sex 
5 1999-01-01 <NA> <NA>  1 sex 
6  <NA> M <NA>  0 race 

和更新原來的表是這樣的:

id dob   sex race survey 
    1 2001-01-01 F HA  1 
    2 2002-02-02 F HA <NA> 
    3  <NA> M W <NA> 

如果required_cols是required_cols<-c("sex","survey")我想輸出表是:

id  dob sex race survey reason 
2 2 2002-02-02 F HA <NA> survey 
3 3  <NA> M W <NA> survey 
4 4 2003-03-03 <NA> AA <NA> survey 
5 5 1999-01-01 <NA> <NA>  1 sex 

和原來的表是:

id  dob sex race survey 
1 1 2001-01-01 F HA  1 
6 6  <NA> M <NA>  0 

我能夠得到使用complete.cases更新原來​​的表,但可以使用一些指導如何以編程未使用的情況下,移動到一個新表標記爲「原因」代碼。

在此先感謝!我是R和stackoverflow的新手,所以如果你有關於如何改進我的問題的建議,請點擊。

回答

2

使用apply逐行找到,如果任何條目有NA,然後刪除(或子集),該行:

required_cols<-c("sex","race") 
df1_with_NA<-df1[apply(is.na(df1[,required_cols]),1,any),] 
df1_without_NA<-df1[!apply(is.na(df1[,required_cols]),1,any),] 
df1_with_NA$reason<-lapply(
     apply(is.na(df1_with_NA[,required_cols]),1,function(x){ 
     required_cols[which(x)] }),paste,collapse=",") 

檢查輸出:

> df1_with_NA 
    id  dob sex race survey reason 
4 4 2003-03-03 <NA> AA <NA>  sex 
5 5 1999-01-01 <NA> <NA>  1 sex,race 
6 6  <NA> M <NA>  0  race 

> df1_without_NA 
    id  dob sex race survey 
1 1 2001-01-01 F HA  1 
2 2 2002-02-02 F HA <NA> 
3 3  <NA> M W <NA> 

您可以更新原始表,如果需要df1<-df1_without_NA

0

執行此操作的一種方法是循環訪問數據框,並使用鏈接的if語句來確定使用is.na()的哪些行是NA。

df1=data.frame(id=c(1:6), 
       dob=as.Date(c("1/1/2001","2/2/2002",NA,"3/3/2003","1/1/1999",NA),"%m/%d/%Y"), 
       sex=c("F","F","M",NA,NA,"M"), 
       race=c("HA","HA","W","AA",NA,NA), 
       survey=c("1",NA,NA,NA,"1","0")) 

for(i in 1:nrow(df1)){ 
    if(is.na(df1$sex[i]) == T & is.na(df1$race[i]) == T){ 
    df1$reason[i] = 'sex & race' 
    }else if(is.na(df1$sex[i]) == T){ 
    df1$reason[i] = 'sex' 
    }else if(is.na(df1$race[i]) == T){ 
    df1$reason[i] = 'race' 
    }else{ 
    df1$reason[i] = NA 
    } 
} 
df1 
# then subset the new df1 where reason is not NA to get the deleted rows 
df2 = subset(df1, df1$reason == NA) 

這有點蠻力方法,但是它的工作原理

id  dob sex race survey  reason 
1 1 2001-01-01 F HA  1  <NA> 
2 2 2002-02-02 F HA <NA>  <NA> 
3 3  <NA> M W <NA>  <NA> 
4 4 2003-03-03 <NA> AA <NA>  sex 
5 5 1999-01-01 <NA> <NA>  1 sex & race 
6 6  <NA> M <NA>  0  race 
+0

感謝@cgage。有很多觀察,所以我關心for循環的性能。 – user2909302

+0

沒問題!這種方法肯定是慢的,@fishtank提供了一個更有效的答案。 – cgage

相關問題