如何比较R中不同data.frames中的两列

时间:2015-09-21 23:28:19

标签: r for-loop matrix dataframe compare

我正在研究R中的第一个真实项目并遇到了问题。我试图在2个不同的data.frames中比较2列。我尝试运行代码,

matrix1 = matrix
for (i in 1:2000){
  if(data.QW[i,1] == data.RS[i,1]){
    matrix1[i,1]== "True"
  }
  else{
    matrix1[i,1]== "False"
  }
}

我收到了这个错误:

Error in Ops.factor(data.QW[i,1], data.RS[i,1]) : 
  level sets of factors are different

我认为这可能是因为QW和RS具有不同的行长度。但我试图看看这些错误可能存在于不同的data.frames中,并根据源文档修复它们。

我也不确定矩阵是否适用于此,或者我是否需要将其转换为向量并且每次都将其转换为矩阵。

对此的任何好读数也将受到赞赏。

3 个答案:

答案 0 :(得分:0)

正如评论中所提到的,提供一个可重现的数据框内容示例将会很有帮助。

根据问题主题的发音,您似乎想要将数据帧A的第1列与数据帧B的第1列进行比较,并将结果存储在逻辑向量中。如果摘要准确无误,请查看here

答案 1 :(得分:0)

评论太长了。

一些观察结果:

  1. 您的专栏data.QW[,1]data.RS[,1]几乎肯定是因素。
  2. 这些因素几乎肯定会有不同的水平(可能其中一个因素在另一个因素中具有一定水平的子集)。发生这种情况时,使用==进行比较将无效。
  3. 如果您使用类似read.csv(...)之类的内容将数据读入这些data.frames,则默认情况下,任何包含字符数据的列都会转换为因子。您可以通过在stringsAsFactors=FALSE的调用中设置read.csv(...)来更改该行为。这是一个非常普遍的问题。
  4. 一旦您解决了因素/级别问题,您可以使用简单地避免循环:data.QW[1:2000,1]==data.RW[1:2000,1]。这将创建一个包含所有比较的长度为2000的向量。不需要循环。当然,这假设两个data.frames至少有2000行。
  5. 这是第2项的一个例子:

    x <- as.factor(rep(LETTERS[1:5],3))   # has levels: A, B, C, D, E
    y <- as.factor(rep(LETTERS[1:3],5))   # has levels: A, B, C
    y==x
    # Error in Ops.factor(y, x) : level sets of factors are different
    

答案 2 :(得分:0)

以下函数compare会比较data.frames或矩阵a,b,以查找ab的行匹配项。它返回b中匹配的第一行位置(经过一些内部排序需要加速思考)。 ab中没有匹配的行的返回值为0。应该处理数字,字符和因子列类型及其混合(后者仅适用于data.frames)。检查函数定义下面的示例。

compare<-function(a,b){

    #################################################
    if(dim(a)[2]!=dim(b)[2]){
        stop("\n Matrices a and b have different number of columns!")
    }
    if(!all(sapply(a, class)==sapply(b, class))){
        stop("\n Matrices a and b have incomparable column data types!")    
    }
    #################################################
    if(is.data.frame(a)){
        i <- sapply(a, is.factor)
        a[i] <- lapply(a[i], as.character)
    }
    if(is.data.frame(b)){
        i <- sapply(b, is.factor)
        b[i] <- lapply(b[i], as.character)
    }
    len1<-dim(a)[1]
    len2<-dim(b)[1]
    ord1<-do.call(order,as.data.frame(a))
    a<-a[ord1,]
    ord2<-do.call(order,as.data.frame(b))
    b<-b[ord2,]     
    #################################################
    found<-rep(0,len1)  
    dims<-dim(a)[2]
    do_dims<-c(1:dim(a)[2]) 
    at<-1
    for(i in 1:len1){
        for(m in do_dims){
            while(b[at,m]<a[i,m]){
                at<-(at+1)      
                if(at>len2){break}              
            }
            if(at>len2){break}
            if(b[at,m]>a[i,m]){break}
            if(m==dims){found[i]<-at}
        }
        if(at>len2){break}
    }
    #################################################
    found<-found[order(ord1)]
    found<-ord2[found]
    return(found)

}
# example data sets:
ncols<-10
nrows<-1E4
a <- matrix(sample(LETTERS,size = (ncols*nrows), replace = T), ncol = ncols, nrow = nrows)
b <- matrix(sample(LETTERS,size = (ncols*nrows), replace = T), ncol = ncols, nrow = nrows)
b <- rbind(a,b) # example of b containing a
b <- b[sample(dim(b)[1],dim(b)[1],replace = F),] 
found<-compare(a,b)

a<-as.data.frame(a) # = conversion to factors
b<-as.data.frame(b) # = conversion to factors
found<-compare(a,b)