如何根据data.frame中的特定向量删除行?

时间:2012-01-08 16:55:36

标签: r

我有一个在线调查数据集,参与者有多次完整的尝试,我需要按行号有选择地删除几个案例。数据存储为data.frame。我意识到我可以手动执行此操作,但我希望将其保留为脚本,以便以后可以使用它,如果需要或有人可以快速有效地复制我所做的事情。

我尝试过:我在多个地方搜索过,但我的问题似乎太简单了。我已经考虑过根据不完整的情况删除行('complete.cases'和'na.omit'),但这并不是我想要的,因为我试图根据data.frame中的特定向量删除一行

数据:

user_id var1 var2 var3
1         NA   13  bob
3       time   37 fred
4     second   NA lisa
5     second   28 lisa

因此,在上面的data.frame中,我有多次尝试用户lisa。我想保留她的最后一次尝试,因为它更完整(var2中没有NA),但我需要根据user_id而不是var3删除该行。

2 个答案:

答案 0 :(得分:1)

从:

开始
> data
  var1 var2 var3  user
1    1   NA    2   bob
2   34    3    1   bob
3   NA   NA    2   bob
4    1    2    3  lisa
5    1   NA    2  lisa
6    3    4    5   joe
7    6   NA    4 simon

首先通过将var1中的非NA值的数量相加到var3来计算完整性得分:

> data$score = apply(data[,c("var1","var2","var3")],1,function(x){sum(!is.na(x))})
> data
  var1 var2 var3  user score
1    1   NA    2   bob     2
2   34    3    1   bob     3
3   NA   NA    2   bob     1
4    1    2    3  lisa     3
5    1   NA    2  lisa     2
6    3    4    5   joe     3
7    6   NA    4 simon     2

然后在每个组中找到具有max(得分)的行。可能有一种更简单的方法:

> pick = unlist(tapply(1:7,data$user,
      function(x){x[data[x,"score"]==max(data[x,"score"])]}))
> pick
  bob   joe  lisa simon 
    2     6     4     7 
> data[pick,]
  var1 var2 var3  user score
2   34    3    1   bob     3
6    3    4    5   joe     3
4    1    2    3  lisa     3
7    6   NA    4 simon     2

如果某人有两行具有相同的分数,他们将出现两次:

> data[2,'var2']=NA
> data$score = apply(data[,c("var1","var2","var3")],1,function(x){sum(!is.na(x))})

现在如果我重新计算选择,我会两次得到鲍勃:

> pick = unlist(tapply(1:7,data$user,
    function(x){x[data[x,"score"]==max(data[x,"score"])]}))
> pick
 bob1  bob2   joe  lisa simon 
    1     2     6     4     7 

只需在拣货计算中返回第一个匹配即可修复:

> pick = unlist(tapply(1:7,data$user,
  function(x){x[data[x,"score"]==max(data[x,"score"])][1]}))
> pick
  bob   joe  lisa simon 
    1     6     4     7 

你没有说复制品你想做什么......

有人可能会在抽签中张贴一条单线......

答案 1 :(得分:0)

setwd("~/Stack Overflow")
MultipleSurveys <- read.table("~/Stack Overflow/ ...
MultipleSurveys.txt", header=T, quote="\"")
SurvDat <- MultipleSurveys[,-ncol(MultipleSurveys)][,-1]
NbNA <- rowSums(is.na(SurvDat)); names(NbNA) <- "NbNA"
AMS <- cbind(MultipleSurveys,NbNA)
minNA <- function(DT){
  NbSurv <- nrow(DT)
  if (NbSurv==1) return(DT)
  else{
    OldRow <- DT[1,]
    for (r in 2:NbSurv){
      NewRow <- DT[r,]
      if (NewRow$NbNA<=OldRow$NbNA) OldRow <- NewRow
    }
    return(OldRow)
  }
}
(SingleSurveys <- by(AMS,AMS$user,minNA))