2016-03-31 12 views
0

zusammenführen Ich habe einen Datenrahmen, der markierte Personen an mehreren Standorten aus mehreren Stichprobenintervallen enthält. Siehe Beispiel unten:Paare von Datenrahmen nacheinander in 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 

Was ich versuche ist getrennt getaggten Personen, die von Intervall zu tun, die ich habe mit diesem für Schleife getan:

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

Und dann Daten verschmelzen Rahmen von Paaren in Sequenz, die ich zur Zeit mit diesem Code zu tun:

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")) 

ich bin sicher, dass es eine effizientere Art und Weise, dies zu tun. Außerdem füge ich fortlaufend Daten zu dem Datensatz hinzu (d. H. Mehr Intervalle), und ich möchte vermeiden, den Code jedes Mal bearbeiten zu müssen, wenn neue Daten hinzugefügt werden. Irgendwelche Ideen?

+0

Sie könnten in split() suchen. – Thomas

Antwort

0

Vielleicht so etwas wie:

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

Das funktioniert gut! Vielen Dank! – KrummerK

0

Nachfolgend finden Sie eine dplyr Lösung, die den Datenrahmen mit sich selbst verbindet und stellt die Ergebnisse in einem Datenrahmen.

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

Das funktioniert auch! Vielen Dank. – KrummerK