2016-08-25 17 views
6

Próbuję połączyć dwa zestawy danych. W przeszłości użyłem merge() z by równej zmiennej, z którą chcę się połączyć. Jednak teraz chciałbym to zrobić za pomocą dwóch zmiennych. Mój pierwszy zestaw danych wygląda mniej więcej tak:Łączenie danych według 2 zmiennych w R

Year Winning_Tm Losing_Tm 
2011 Texas   Washington 
2012 Alabama  South Carolina 
2013 Tennessee  Texas 

Wtedy mam inny zestaw danych o randze każdego zespołu (jest to bardzo uproszczony) dla każdego roku. Tak:

Year Team    Rank 
2011 Texas   32 
2011 Washington  34 
2012 South Carolina 45 
2012 Alabama   12 
2013 Texas   6 
2013 Tennessee  51 

chciałbym połączyć je tak Mam zestaw danych, który wygląda tak:

Year Winning_Tm Winning_TM_rank Losing_Tm  Losing_Tm_rank 
2011 Texas   32     Washington  34 
2012 Alabama  12     South Carolina 45 
2013 Tennessee  51     Texas   6 

Mam nadzieję, że nie jest to prosty sposób, aby to zrobić, ale może to być bardziej skomplikowane. Dzięki!

Odpowiedz

2

Dwa oddzielne scala. Będziesz musiał zawinąć listę zmiennych by w c(), a ponieważ zmienne mają różne nazwy, potrzebujesz by.x i by.y. Następnie możesz zmienić nazwy zmiennych rangowych.

Nazwie twoich danych winlose i teamrank, odpowiednio.Potem trzeba:

first_merge <- merge(winlose, teamrank, by.x = c('Year', 'Winning_Tm'), by.y = c('Year', 'Team')) 
second_merge <- merge(first_merge, teamrank, by.x = c('Year', 'Losing_Tm'), by.y = c('Year', 'Team')) 

Zmiana nazwy zmiennych:

names(second_merge)[names(second_merge) == 'Rank.x'] <- 'Winning_Tm_rank' 
names(second_merge)[names(second_merge) == 'Rank.y'] <- 'Losing_Tm_rank' 
+1

Należy pamiętać, że 'rangi' jest wbudowaną funkcją, która może skutkować niepożądanymi kolizjami z nazwami –

+2

Ah, dobry połów, I Nigdy nie użyłem tej funkcji Edytowałem moją odpowiedź, aby zmienić 'rank' na' teamrank'. –

4

I zamieszczonym dane (spróbuj zawierać dput o tym następnym razem):

A <- data.frame(
    Year = c(2011, 2012, 2013), 
    Winning_Tm = c("Texas","Alabama","Tennessee"), 
    Losing_Tm = c("Washington","South Carolina", "Texas"), 
    stringsAsFactors = FALSE 
) 

B <- data.frame(
    Year = c("2011","2011","2012","2012","2013","2013"), 
    Team = c("Texas","Washington","South Carolina","Alabama","Texas","Tennessee"), 
    Rank = c(32,34,45,12,6,51), 
    stringsAsFactors = FALSE 
) 

Można melt pierwszy dataframe użyciu pakietu reshape2:

library(reshape2) 

A <- melt(A, id.vars = "Year") 
names(A)[3] <- "Team" 

Teraz wygląda to tak :

> A 
    Year variable   Team 
1 2011 Winning_Tm   Texas 
2 2012 Winning_Tm  Alabama 
3 2013 Winning_Tm  Tennessee 
4 2011 Losing_Tm  Washington 
5 2012 Losing_Tm South Carolina 
6 2013 Losing_Tm   Texas 

Możesz następnie scalić zestawy danych ze sobą za pomocą dwóch kolumn zainteresowania:

AB <- merge(A, B, by=c("Year","Team")) 

który wygląda tak:

> AB 
    Year   Team variable Rank 
1 2011   Texas Winning_Tm 32 
2 2011  Washington Losing_Tm 34 
3 2012  Alabama Winning_Tm 12 
4 2012 South Carolina Losing_Tm 45 
5 2013  Tennessee Winning_Tm 51 
6 2013   Texas Losing_Tm 6 

Następnie za pomocą polecenia reshape od podstawy R można zmienić AB do szerokiego formatu:

reshape(AB, idvar = "Year", timevar = "variable", direction = "wide") 

Wynik:

Year Team.Winning_Tm Rank.Winning_Tm Team.Losing_Tm Rank.Losing_Tm 
1 2011   Texas    32  Washington    34 
3 2012   Alabama    12 South Carolina    45 
5 2013  Tennessee    51   Texas    6 
+1

Użyłem twojej metody i działa dobrze, tyle tylko, że wydaje się, że to zagmatwane zespoły, które powtarzają się (myślę). tutaj jest komunikat ostrzegawczy: Komunikaty ostrzegawcze: 1: W reshapeWide (dane, idvar = idvar, timevar = timevar, zmienne = zmieniające się,: wiele wierszy zgodnych dla zmiennej = L_Tm: pierwsze pobrane 2: W reshapeWide (dane, idvar = idvar, timevar = timevar, zmienna = zmieniająca się,: wiele wierszy zgodnych dla zmiennej = W_Tm: pierwsza wzięta –

+0

Dobra litera @ a.powell Czy wynikowa ramka danych po 'reshape' pokazuje tylko powtórzone zespoły raz? – Warner

+0

To pokazało tylko gry z "Air Force", pierwszego alfabetycznego zespołu na liście, i przekształcić je grając same siebie –

2

Jeśli jesteś zaznajomiony z SQL dość skomplikowane, ale szybki sposób zrobić to wszystko w jednym kroku byłoby:

res <- sqldf("SELECT l.*, 
        max(case when l.Winning_Tm = r.Team then r.Rank else 0 end) as Winning_Tm_rank, 
        max(case when l.Losing_Tm = r.Team then r.Rank else 0 end) as Losing_Tm_rank 
      FROM  df1 as l 
      inner join df2 as r 
      on  (l.Winning_Tm = r.Team 
      OR  l.Losing_Tm = r.Team) 
      AND  l.Year = r.Year 
      group by l.Year, l.Winning_Tm, l.Losing_Tm") 

res 
    Year Winning_Tm  Losing_Tm Winning_Tm_rank Losing_Tm_rank 
1 2011  Texas  Washington    32    34 
2 2012 Alabama South_Carolina    12    45 
3 2013 Tennessee   Texas    51    6 

danych:

df1 <- read.table(header=T,text="Year Winning_Tm Losing_Tm 
2011 Texas   Washington 
2012 Alabama  South_Carolina 
2013 Tennessee  Texas") 

df2<- read.table(header=T,text="Year Team Rank 
2011 Texas   32 
2011 Washington  34 
2012 South_Carolina 45 
2012 Alabama   12 
2013 Texas   6 
2013 Tennessee  51") 
0

Niech X1 zawierać swój pierwszy stół i X2 zawierać swoją drugą tabelę.

library(dplyr) 
library(plyr) 

## Create a joint table to work with 
XX <- inner_join(X1, X2, by="Year") 

## Compute the ranks 
f <- function(x, y, r) { r[ as.character(x) == as.character(y) ] } 
rr <- ddply(XX, "Year", summarise, 
    Winning_TM_Rank = f(Team, Winning_Tm, Rank), 
    Losing_TM_Rank = f(Team, Losing_Tm, Rank)) 

## Combine the results and reorder the columns 
inner_join(X1, rr)[,c(1,2,4,3,5)]