根据字符重复项的数量分配值

时间:2011-07-04 06:21:45

标签: r conditional duplicate-data

对于问题后的突发问题,我们深表歉意。尽我所能搜索,但我有一个艰巨的任务,想出一个非常非常大的程序,我仍然是R的新手,所以我很感激到目前为止我得到的所有快速帮助。

示例问题的假例子

Gene <- c("A","B","C","A","B","C","A","B","C")
> IntensityValue <- c(1,10,20,3,NA,23,NA,NA,22)
> ProceedTest <- c(2,2,2,2,-1,2,-1,-1,2)
> ExampleData <- list(Gene=Gene, IntensityValue=IntensityValue, ProceedTest=ProceedTest)
> ExampleData <- as.data.frame(ExampleData)
> ExampleData
Gene IntensityValue ProceedTest
 A              1           2
 B             10           2
 C             20           2
 A              3           2
 B             NA          -1
 C             23           2
 A             NA          -1
 B             NA          -1
 C             22           2

ProceedTest是一个分数,表示测试是否应该继续进行。得分为2表示将数据考虑在内,得分为-1表示测试不会将数据考虑在内。

您会注意到基因B有NA出现两次,A有NA只出现一次。我希望R能够识别出对于基因B,NA出现两次。这样任何时候NA对于给定的基因(B)出现两次,零值替换NA,随后的-1变为2.我希望R忽略A的NA并继续离开Proceed测试价值观。

更改的数据应如下所示:

Gene IntensityValue ProceedTest
  A              1           2
  B             10           2
  C             20           2
  A              3           2
  B              0           2
  C             23           2
  A             NA          -1
  B              0           2
  C             22           2

这可能是不可能的,但如果是的话,我希望能够说如果基因没有NA,则ProceedTest值变为-1。

Final Dataset
 Gene IntensityValue ProceedTest
  A              1           2
  B             10           2
  C             20          -1
  A              3           2
  B              0           2
  C             23          -1
  A             NA          -1
  B              0           2
  C             22          -1

总结。基因A只有一个NA,因此没有任何变化。基因B具有两个NA值,因此它获得全部2,并且NA在强度值列中变为零。基因C变为-1,因为它不包含任何NA(改变强度值并不重要)。

我希望这很清楚,我也知道我的其他问题有点容易,所以我希望这个特别的问题不是那么简单,我应该做更多的研究来自己找到答案。 / p>

提前感谢您的帮助,

2 个答案:

答案 0 :(得分:2)

如果您不关心data.frame的顺序,ddply包中的plyr可以解决问题:

ddply(ExampleData, "Gene", function(dfr){
        #here, dfr is the part of your original data.frame
        #only for the 'current value' of Gene
        numNA<-sum(is.na(dfr$IntensityValue))
        if(numNA>1)
        {
            dfr$IntensityValue<-0
            dfr$ProceedTest<-2
        }
        else if(numNA==0)
        {
            dfr$ProceedTest<- -1
        }
        dfr
    })

但是还有很多其他解决方案。

答案 1 :(得分:0)

需要注意的是,几乎可以肯定有更有效的方法(如果你的数据对每个基因有很多重复,那么合并操作重复包含计数的非常精简的data.frame会占用大量内存) :

Gene <- c("A","B","C","A","B","C","A","B","C")
IntensityValue <- c(1,10,20,3,NA,23,NA,NA,22)
ProceedTest <- c(2,2,2,2,-1,2,-1,-1,2)
ExampleData <- list(Gene=Gene, IntensityValue=IntensityValue, ProceedTest=ProceedTest)
ExampleData <- as.data.frame(ExampleData)
ExampleData

num.na <- function(x) {
  sum(is.na(x))
}
ED.numna <- by(data=ExampleData,Gene,num.na)
# res.name is what you want the result column to be named
  #ideally would pull this from the call via something like as.character(attr(x,"call"))
as.data.frame.by <- function(x,res.name=NA) {
  stopifnot(length(dimnames(x))==1) # Only 1d case handled for now
  df <- data.frame(by = names(x), res = as.numeric(x) )
  names(df)[names(df)=="by"] <- names(dimnames(x))
  if(!is.na(res.name)) {
    names(df)[names(df)=="res"] <- res.name
  }
  df
}
ExampleData <- merge(ExampleData,as.data.frame(ED.numna,"count"))
ExampleData$IntensityValue[ExampleData$count > 1] <- 0