比较R中相同大小的两个数据帧中的每个单元格是否相等

时间:2017-01-22 11:43:02

标签: r dataframe

我有2个数据帧,比如A和B,大小相等(行和列)。我想输出一个相同大小的数据帧,比如C,所有的值都是0或1。

C[i,j] = 0, if A[i,j] != B[i,j]
C[i,j] = 1, if A[i,j] == B[i,j]

我不想使用循环或ifelse语句,因为我已成功完成,但需要很长时间。如果有任何其他直接的方法来做同样的事情,那将非常有帮助。感谢

4 个答案:

答案 0 :(得分:6)

只需比较两个data.frame以获得具有相同大小的matrix,并在单元格中指示比较结果的逻辑:

A <- mtcars
B <- mtcars

A == B

结果(仅显示第一行):

                     mpg  cyl disp   hp drat   wt qsec   vs   am gear carb
Mazda RX4           TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
Mazda RX4 Wag       TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
Datsun 710          TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
Hornet 4 Drive      TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE

要从比较中获得data.frame

C <- as.data.frame(A == B)

您可以使用R中的TRUE == 1和FALSE == 0(OP要求)将结果明确强制转换为整数的事实:

as.data.frame(lapply(as.data.frame(A == B), as.integer))

乘以1(在另一个答案中提出)更漂亮,可能更有效(避免:

as.data.frame(1 * (A == B))

编辑++ [添加基准;为了一致性而改进了基准测试]:

基于data.frame和10 Mio的不同答案之间的基准。行(约260 MB)......

library(microbenchmark)   # install.packages("microbenchmark")
library(data.table)

A <- data.frame(col1 = 1:1E7,
                col2 = rep(c("a string", "another string"), 1E7/2),
                col3 = 1:1E7,
                col4 = 1:1E7,
                col5 = rep(LETTERS[1:10],1E6),
                stringsAsFactors = FALSE)
B <- A
B[1,1]=100  # change one cell to create a copy of the data.frame

microbenchmark(DF.equals       = as.data.frame(A == B),
               DF.mult         = as.data.frame(1 * (A == B)),
               DF.map          = as.data.frame(Map(`==`, A, B)),
               matrix.equals   = A == B,
               matrix.mult     = 1 * (A == B),
               matrix.map      = do.call(cbind, Map(`==`, A, B)),  # causes a warning: duplicated levels in factors are deprecated
               list.map        = Map(`==`, A, B),                  # fast cause it does not construct a matrix but only vectors
               times = 100)

显示Map()函数作为明显的赢家(在我的系统上)比其他变体快两到四倍,结果为matrixdata.frame快得多:

Unit: milliseconds
          expr      min       lq     mean   median       uq      max neval    cld
     DF.equals 627.2541 630.7565 654.0266 635.1831 678.8903 686.0753   100     e 
      DF.mult  743.8531 751.7933 781.1876 796.2282 799.1881 848.2455   100      f
        DF.map 169.6967 170.5842 176.5944 171.5072 173.5665 223.3354   100 a     
 matrix.equals 294.2570 297.5330 311.8095 299.8093 345.0827 351.9193   100   c   
  matrix.mult  402.6166 406.5279 422.9322 408.3012 453.4484 602.2139   100    d  
    matrix.map 206.2596 208.4230 217.8891 209.8968 211.4139 266.1867   100  b    
      list.map 169.1922 170.5403 175.7539 171.4602 173.3891 224.7062   100 a   

<强>顺便说一句:

我真正喜欢的是你现在如何做一些统计数据,例如: G。计算每列不匹配的数量(如果使用rowSums,则计算行数):

colSums(C != TRUE)

colSums(A != B)

获得可用于自动检查前提条件的结果(例如,不允许不匹配):

 mpg  cyl disp   hp drat   wt qsec   vs   am gear carb 
   0    0    0    0    0    0    0    0    0    0    0 

答案 1 :(得分:5)

尝试:

C <- data.frame(1 * (A == B))

1*用于根据需要将TRUE / FALSE设置为0/1。

答案 2 :(得分:4)

我们可以使用Map来比较两个data.frame'A'和'B'

的相应列
Map(`==`, A, B)

优点是我们在工作区中获得list个逻辑vector而不是matrix。如果数据集非常大,那么可能是内存限制以获得矩阵输出

答案 3 :(得分:1)

此示例生成一个T / F矩阵,可以在R

中有效地将其视为0/1
x = matrix(1:9, nrow = 3)
y = matrix(9:1, nrow = 3)
x == y

由于答案中还有其他一些建议,我认为我测试哪个是最快的,因为这是问题的要求。

此处equals指的是A == B解决方案,map_xy是Map解决方案。

microbenchmark(equals(x,y), map_xy(x,y), times = 1000)
Unit: nanoseconds
         expr   min    lq      mean  median    uq   max neval
 equals(x, y)   360   399   468.491   459.0   508  3473  1000
 map_xy(x, y) 10909 12114 13506.830 13132.5 14158 77743  1000

看起来equals是一个更快的选择 - 但是Map答案表明它可能会在更大的数据集中表现更好。所以我再次使用合理大小的数据进行测试:

x_big = matrix(1:900000, nrow = 3)
> y_big = matrix(900000:1, nrow = 3)
> microbenchmark(equals(x_big,y_big), map_xy(x_big,y_big), times = 100)
Unit: milliseconds
                 expr        min          lq        mean      median          uq
 equals(x_big, y_big)   1.579069    2.118332    2.515257    2.225747    2.375377
 map_xy(x_big, y_big) 846.172497 1040.383027 1165.354138 1147.239396 1321.166762
        max neval
   21.48414   100
 1489.81884   100

这表明等于仍然是更快的选择。

修改

对于评论,这里是每个功能的代码。我稍微编辑了这些以将输出转换为data.frame(虽然我个人认为这一步是不必要的)

equals = function(x,y){
  as.data.frame(x == y)
}

map_xy = function(x,y){
  Map('==', x, y) %>% 
    unlist(.) %>%
    matrix(., nrow = 3) %>%
    as.data.frame(.)
}

这会改变基准测试结果,但不会改变结果:

对于小矩阵:

Unit: microseconds
         expr     min       lq      mean   median       uq      max neval
 equals(x, y)  18.090  20.3205  24.31075  22.0205  23.7285  781.048  1000
 map_xy(x, y) 172.699 186.0775 209.39585 193.3645 204.0220 2646.419  1000

对于大型矩阵:

Unit: milliseconds
                 expr       min        lq     mean    median        uq      max
 equals(x_big, y_big)  533.3274  646.0605  744.063  705.4923  871.3479 1067.411
 map_xy(x_big, y_big) 1637.2882 1820.8714 1938.458 1921.2563 2041.0533 2564.669
 neval
   100
   100

如果你想要我最初使用的功能 - 只需取出转换成data.frame的代码即可。