【问题标题】:How do I remove a row based on a specific vector within a data.frame?如何根据 data.frame 中的特定向量删除一行?
【发布时间】:2012-01-08 16:55:36
【问题描述】:

我有一个在线调查数据集,其中参与者进行了多次完整尝试,我需要按行号选择性地删除几个案例。数据存储为 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 的行。

【问题讨论】:

  • 明确地说,您要删除除特定用户 (var3) 的所有案例之外的所有案例,并且要先删除那些缺少数据的案例?
  • 那么“完整性”是 var1 和 var2 中非 NA 的数量吗?您想为 var3 中的每个值保留最完整的行吗?所以即使鲍勃和丽莎第一次一样不完整,他的条目仍然存在,因为他从来没有做得更好?对吗?
  • 是的,我想从上面的数据中删除第 4 行,即 user_id 4。是的,实际上对你们俩都是。我不关心有几个 NA 的行,而只保留多次尝试调查的受访者的最完整尝试。
  • 如果丽莎有两条完整的记录怎么办?如果 Bob 有两条记录(即行),每条记录都有一个 NA 怎么办?在这两种情况下,您要保留这两种记录吗?
  • @JoshO'Brien 那时我需要应用另一个过滤器并使用日期/时间选择最近的尝试。

标签: r


【解决方案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 到 var3 中非 NA 值的数量相加来计算完整性分数:

> 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(score) 的行。可能有更简单的方法来做到这一点:

> 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 我会得到两次 bob:

> 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 

你没有说你想对重复项做什么......

有人可能会在 tic 中发布一个单行...

【讨论】:

  • 这很有帮助,谢谢。它在引导我的方向。我认为另一种选择是按用户和日期/时间过滤它,我应该将其包含在我的解释中。
【解决方案2】:
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))

【讨论】:

    猜你喜欢
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多