2012-04-28 25 views
-2

我有data.frame甲 且其含有的ř濾除一個子集

如何創建一個data.frameÇ這與數據data.frame甲子集的data.frame乙。框架B排除? 感謝您的幫助。

+4

請修改你的問題如下這裏列出的準則:http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – Chase 2012-04-28 20:10:13

回答

3

得到一個不在B中的行

C = A[! data.frame(t(A)) %in% data.frame(t(B)), ] 
+0

非常感謝。這非常有幫助 – 2012-04-28 20:32:53

+0

這可能不是最快的,但它似乎是最安全的,因爲它佔據了行中的數據而不是行名。如果行名稱已被混合或重新排列,則行名稱可能有風險。+1 – 2012-04-28 20:59:22

+2

@Tyler - 如果OP提供了一個數據實際看起來像樣的例子,這是最安全的,所以它不會留在那些試圖回答的人的想象中:) – Chase 2012-04-28 21:05:48

1
A <- data.frame(x = 1:10, y = 1:10) 
#Random subset of A in B 
B <- A[sample(nrow(A),3),] 
#get A that is not in B 
C <- A[-as.integer(rownames(B)),] 

性能測試面對面的人mplourde的回答是:

library(rbenchmark) 
f1 <- function() A[- as.integer(rownames(B)),] 
f2 <- function() A[! data.frame(t(A)) %in% data.frame(t(B)), ] 
benchmark(f1(), f2(), replications = 10000, 
      columns = c("test", "elapsed", "relative"), 
      order = "elapsed" 
     ) 

    test elapsed relative 
1 f1() 1.531 1.0000 
2 f2() 8.846 5.7779 

望着rownames是約6倍快。兩次調用轉置會導致計算成本高昂。

1

如果B是一個真正的一個子集,它可以檢查與:

C <- A[!rownames(A) %in% rownames(B), , drop = FALSE] 

C <- A[setdiff(rownames(A), rownames(B)), , drop = FALSE] 
0

這就是:

if(!identical(A[rownames(B), , drop = FALSE], B)) stop("B is not a subset of A!") 

那麼你可以通過rownames過濾不是最快的,可能會非常緩慢,但它是mplourde的替代方案,它考慮了行數據並且應該可以工作關於flodel批評的混合數據。它依賴於從qdap包paste2功能,因爲我打算在enxt個月或2個內釋放尚不存在:

粘貼2個功能:

paste2 <- function(multi.columns, sep=".", handle.na=TRUE, trim=TRUE){ 

    if (trim) multi.columns <- lapply(multi.columns, function(x) { 
      gsub("^\\s+|\\s+$", "", x) 
     } 
    ) 

    if (!is.data.frame(multi.columns) & is.list(multi.columns)) { 
     multi.columns <- do.call('cbind', multi.columns) 
     } 

    m <- if(handle.na){ 
       apply(multi.columns, 1, function(x){if(any(is.na(x))){ 
         NA 
       } else { 
         paste(x, collapse = sep) 
       } 
      } 
     ) 
     } else { 
      apply(multi.columns, 1, paste, collapse = sep) 
    } 
    names(m) <- NULL 
    return(m) 
} 

#Flodel的混合數據集:

A <- data.frame(x = 1:4, y = as.character(1:4)); B <- A[1:2, ] 

#我的方法:

A[!paste2(A)%in%paste2(B), ] 
2

如果此B數據集確實是第一個數據集的嵌套版本,那麼必須建立索引以創建此數據集。恕我直言,我們不應該討論數據集之間的差異,而是否定創建B數據集的原始索引。下面是我的意思的例子:

A <- mtcars 
B <- mtcars[mtcars$cyl==6, ] 
C <- mtcars[mtcars$cyl!=6, ] 
1

這裏有兩個data.table的解決方案,這將是內存和時間效率

render_markdown(strict = T) 
library(data.table) 
# some biggish data 
set.seed(1234) 
ADT <- data.table(x = seq.int(1e+07), y = seq.int(1e+07)) 

.rows <- sample(nrow(ADT), 30000) 
# Random subset of A in B 
BDT <- ADT[.rows, ] 

# set keys for fast merge 
setkey(ADT, x) 
setkey(BDT, x) 
## how CDT <- ADT[-ADT[BDT,which=T]] the data as `data.frames for fastest 
## alternative 
A <- copy(ADT) 
setattr(A, "class", "data.frame") 
B <- copy(BDT) 
setattr(B, "class", "data.frame") 
f2 <- function() noBDT <- ADT[-ADT[BDT, which = T]] 
f3 <- function() noBDT2 <- ADT[-BDT[, x]] 
f1 <- function() noB <- A[-as.integer(rownames(B)), ] 

library(rbenchmark) 
benchmark(base = f1(),DT = f2(), DT2 = f3(), replications = 3) 

## test replications elapsed relative user.self sys.self 
## 2 DT   3 0.92 1.108  0.77  0.15  
## 1 base   3 3.72 4.482  3.19  0.52   
## 3 DT2   3 0.83 1.000  0.72  0.11  
+0

不確定這對基礎是否公平:大部分時間是將rownames轉換爲整數,不是嗎?由於您知道密鑰是唯一的(已知緩慢的bug),所以data = table連接也應該更快,因爲mult =「first」。這個示例數據可能與密鑰相同,因此與行號相同(根本不需要加入)。 – 2012-10-08 07:12:00