2015-09-23 82 views
2

假设我有两个数据帧:[R子集数据,而不用循环

A <- data.frame("SerialNum" = integer(), "Year" = integer(), stringsAsFactors = F) 
    A[1,] <- c(93843, 2001) 
    A[2,] <- c(12458, 2007) 
    A[3,] <- c(11112, 2000) 
    A[4,] <- c(18293, 2013) 
    A[5,] <- c(81203, 2014) 
    A[6,] <- c(11112, 2001) 
    A[7,] <- c(11112, 2013) 
    A[8,] <- c(11112, 2014) 

B <- data.frame("SerialNum" = integer(), "Year" = integer(), stringsAsFactors= F) 
B[1:3,] <- rbind(c(11112, 2000), c(18293, 2013),c(81203, 2014)) 
B[4,] <- c(48639, 2012) 
B[5,] <- c(00128, 2003) 
B[6,] <- c(67942, 2005) 

我想要做的是创造新的数据帧:A_Match它包含了所有的A常见条目,以BB_Match所有B的条目与A共有。用for循环做这件事很容易,但对于我的实际数据来说太慢了。与我的数据棘手的部分是,不同的年份可能包含相同的序列号,所以我必须检查序列号和年份,以正确地分类我的数据。在R中做什么是面向对象的方法?我不确定哪些功能可以帮助我完成此任务。我的for循环

L_A  <- nrow(A) 
L_B  <- nrow(B) 
A_Inds <- integer() 
B_Inds <- integer() 

for (i in 1:L_A){ 
    IncNums <- which(B$SerialNum == A$SerialNum[i]) 
    YNums <- which(B$Year == A$Year[i]) 
    B_Inds <- union(B_Inds, intersect(IncNums, YNums)) 
} 

for (i in 1:L_B){ 
    IncNums <- which(A$SerialNum == B$SerialNum[i]) 
    YNums <- which(A$Year == B$Year[i]) 
    A_Inds <- union(A_Inds, intersect(IncNums, YNums)) 
} 

A_Match <- A[unique(A_Inds),] 
B_Match <- B[unique(B_Inds),] 

回答

2

您可以使用%in%检查,如果从一个数据帧的每个序列号是存在于对方,然后使用标准排索引来限制比赛:

(A_Match <- A[A$SerialNum %in% B$SerialNum,]) 
# SerialNum Year 
# 3  11112 2000 
# 4  18293 2013 
# 5  81203 2014 
(B_Match <- B[B$SerialNum %in% A$SerialNum,]) 
# SerialNum Year 
# 1  11112 2000 
# 2  18293 2013 
# 3  81203 2014 
+0

感谢您的回答,但我忘记了一个重要的细节,相同的序列号。因此,我需要能够根据序列号和年份对数据进行分类。这将如何改变你的方法? – Mnifldz

+1

那么,一种方法是使用'粘贴(A $ SerialNum,A $ Year)'和'粘贴(B $ SerialNum,B $ Year)'。 – josliber

+0

完美的作品!谢谢。 – Mnifldz

0

我相信这也是等价的,也许对于大型数据集更好:

library(dplyr) 
semi_join(A,B)