2016-03-31 3 views
0

У меня есть кадр данных, который содержит помеченных лиц на нескольких сайтах с нескольких интервалов выборки. Смотрите пример ниже:Слияние пар данных в последовательности в R

> df 
    Tag Site Interval Ind_ID 
1 507 Golden  7  1 
2 507 Golden  8  1 
3 552 Golden  2  1 
4 552 Golden  1  1 
5 847 Golden  4  1 
6 847 Golden  6  1 
8 847 Golden  5  1 
9 847 Golden  3  1 
31 541 Golden  1  1 
33 541 Golden  3  1 
34 541 Golden  4  1 
35 541 Golden  7  1 
36 541 Golden  6  1 
37 541 Golden  5  1 
39 810 Golden  7  1 
40 810 Golden  8  1 
41 840 Golden  7  1 
42 840 Golden  8  1 
43 840 Golden  3  1 
44 840 Golden  2  1 

То, что я пытаюсь сделать, это отдельные меченые особи по интервалу, который я сделал с помощью этого цикл:

for (i in 1:nlevels(factor(df$Interval))){ 
    I<-subset(df,Interval==levels(factor(df$Interval))[i]) 
    assign(paste("Interval_", i, sep = ""), I)} 

А затем объединить кадры данных парами в последовательность, которую я сейчас делаю, используя этот код:

IPl2<-merge(Interval_1, Interval_2, by=c("Tag", "Site", "Ind_ID")) 
IPl3<-merge(Interval_2, Interval_3, by=c("Tag", "Site", "Ind_ID")) 
IPl4<-merge(Interval_3, Interval_4, by=c("Tag", "Site", "Ind_ID")) 
IPl5<-merge(Interval_4, Interval_5, by=c("Tag", "Site", "Ind_ID")) 
IPl6<-merge(Interval_5, Interval_6, by=c("Tag", "Site", "Ind_ID")) 
IPl7<-merge(Interval_6, Interval_7, by=c("Tag", "Site", "Ind_ID")) 
IPl8<-merge(Interval_7, Interval_8, by=c("Tag", "Site", "Ind_ID")) 

Я уверен, что есть более эффективный способ сделать это. Кроме того, я постоянно добавляю данные в набор данных (т. Е. Больше интервалов), и я бы хотел избежать необходимости редактировать код при каждом добавлении новых данных. Есть идеи?

+0

Возможно, вы захотите изучить split(). – Thomas

ответ

0

Может быть что-то вроде этого:

dfs <- split(df,df$Interval) 
n <- nlevels(factor(df$Interval))-1 
results <- setNames(vector("list",length = n),paste0("IPl",2:(n+1))) 
for (i in seq_len(n)){ 
    results[[i]] <- merge(dfs[[i]],dfs[[i+1]],by = c('Tag','Site','Ind_ID')) 
} 

> head(results) 

$IPl2 
    Tag Site Ind_ID Interval.x Interval.y 
1 552 Golden  1   1   2 

$IPl3 
    Tag Site Ind_ID Interval.x Interval.y 
1 840 Golden  1   2   3 

$IPl4 
    Tag Site Ind_ID Interval.x Interval.y 
1 541 Golden  1   3   4 
2 847 Golden  1   3   4 

$IPl5 
    Tag Site Ind_ID Interval.x Interval.y 
1 541 Golden  1   4   5 
2 847 Golden  1   4   5 

$IPl6 
    Tag Site Ind_ID Interval.x Interval.y 
1 541 Golden  1   5   6 
2 847 Golden  1   5   6 

$IPl7 
    Tag Site Ind_ID Interval.x Interval.y 
1 541 Golden  1   6   7 
+0

Это хорошо работает! Спасибо! – KrummerK

0

Ниже dplyr решения, которое соединяет фрейм данных с самими собой и помещает результаты в кадре данных.

library(dplyr) 
## Join the 'df' to itself based on the intervals to compare; this is done by 
## creating a key to indicate which intervals to join on. 
resultdf <- 
    ## Create match_interval to next sequential value 
    df %>% mutate(match_interval = paste0('IPl', as.numeric(Interval)+1)) %>% arrange(Interval, Site) %>% 
    ## Join to self by match_interval and other columns. 
    inner_join(df %>% mutate(match_interval = paste0('IPl', as.numeric(Interval))), 
       by = c('Tag', 'Site', 'Ind_ID', 'match_interval')) %>% 
    ## Order columns 
    select(match_interval, Tag, Site, Ind_ID, Interval.x, Interval.y) 


resultsdf 

## match_interval Tag Site Ind_ID Interval.x Interval.y 
## 1   IPl2 552 Golden  1   1   2 
## 2   IPl3 840 Golden  1   2   3 
## 3   IPl4 847 Golden  1   3   4 
## 4   IPl4 541 Golden  1   3   4 
## 5   IPl5 847 Golden  1   4   5 
## 6   IPl5 541 Golden  1   4   5 
## 7   IPl6 847 Golden  1   5   6 
## 8   IPl6 541 Golden  1   5   6 
## 9   IPl7 541 Golden  1   6   7 
## 10   IPl8 507 Golden  1   7   8 
## 11   IPl8 810 Golden  1   7   8 
## 12   IPl8 840 Golden  1   7   8 
+0

Это тоже работает! Спасибо. – KrummerK