2015-07-09 21 views
6

Vorrei combinare due tabelle in base al nome, al cognome e all'anno e creare una nuova variabile binaria che indica se la riga della tabella 1 era presente nella seconda tabella.Come unire/unire due tabelle usando i valori dei caratteri?

prima tabella è un insieme di dati panel set di alcuni attributi di giocatori NBA nel corso di una stagione:

firstname<-c("Michael","Michael","Michael","Magic","Magic","Magic","Larry","Larry") 
    lastname<-c("Jordan","Jordan","Jordan","Johnson","Johnson","Johnson","Bird","Bird") 
    year<-c("1991","1992","1993","1991","1992","1993","1992","1992") 

    season<-data.frame(firstname,lastname,year) 


    firstname lastname  year 
    1 Michael  Jordan   1991 
    2 Michael  Jordan   1992 
    3 Michael  Jordan   1993 
    4 Magic  Johnson  1991 
    5 Magic  Johnson  1992 
    6 Magic  Johnson  1993 
    7 Larry  Bird   1992 
    8 Larry  Bird   1992 

Il secondo data.frame è un insieme di dati panel di alcuni attributi di giocatori NBA selezionato per l'All-Star gioco:

firstname<-c("Michael","Michael","Michael","Magic","Magic","Magic") 
    lastname<-c("Jordan","Jordan","Jordan","Johnson","Johnson","Johnson") 
    year<-c("1991","1992","1993","1991","1992","1993") 

    ALLSTARS<-data.frame(firstname,lastname,year) 



    firstname lastname year 
    1 Michael  Jordan 1991 
    2 Michael  Jordan 1992 
    3 Michael  Jordan 1993 
    4 Magic  Johnson 1991 
    5 Magic  Johnson 1992 
    6 Magic  Johnson 1993 

mio risultato desiderato assomiglia:

firstname lastname year allstars 

    1 Michael Jordan 1991 1 
    2 Michael Jordan 1992 1 
    3 Michael Jordan 1993 1 
    4 Magic Johnson 1991 1 
    5 Magic Johnson 1992 1 
    6 Magic Johnson 1993 1 
    7 Larry Bird 1992 0 
    8 Larry Bird 1992 0 

I ho provato ad usare un join di sinistra. Ma non so se questo ha un senso:

test<-join(season, ALLSTARS, by =c("lastname","firstname","year") , type = "left", match = "all") 
+0

Vorrei usare 'left_join' o' right_join' dal pacchetto dplyr come nella risposta di David. Ma per risolvere il tuo codice: sembra che tu stia usando 'join()' dal pacchetto plyr. Eravate quasi arrivati, basta che premete il comando con 'ALLSTARS $ allstars <- 1'. Quindi esegui il join e converti i valori di 'NA' in 0. –

+0

possibile duplicato di [Come unire (unire) frame di dati (interno, esterno, sinistro, destro)?] (Http://stackoverflow.com/questions/1299871/how-to-join-merge-data-frames-inner-outer-left-right) –

+0

@ Sam Firke. E 'stato semplicemente straordinario! :) Grazie. Ha funzionato perfettamente! –

risposta

1

Sembra che si sta utilizzando join() dal pacchetto plyr. Eri quasi arrivato: basta preordinare il comando con ALLSTARS$allstars <- 1. Allora il tuo unirsi come è scritto e, infine, convertire i valori NA a 0. Quindi:

ALLSTARS$allstars <- 1 
test <- join(season, ALLSTARS, by =c("lastname","firstname","year") , type = "left", match = "all") 
test$allstars[is.na(test$allstars)] <- 0 

Risultato:

firstname lastname year allstars 
1 Michael Jordan 1991  1 
2 Michael Jordan 1992  1 
3 Michael Jordan 1993  1 
4  Magic Johnson 1991  1 
5  Magic Johnson 1992  1 
6  Magic Johnson 1993  1 
7  Larry  Bird 1992  0 
8  Larry  Bird 1992  0 

Anche se io personalmente userei left_join o right_join dal pacchetto dplyr, come in La risposta di David, invece di plyr's join(). Si noti inoltre che in realtà non è necessario l'argomento by di join() poiché per impostazione predefinita la funzione proverà a collegarsi a tutti i campi con nomi comuni, che è ciò che si desidera qui.

4

Ecco una soluzione semplice utilizzando data.table binario unirsi, che consente di aggiornare una colonna di riferimento, mentre joing

library(data.table) 
setkey(setDT(season), firstname, lastname, year)[ALLSTARS, allstars := 1L] 
season 
# firstname lastname year allstars 
# 1:  Larry  Bird 1992  NA 
# 2:  Larry  Bird 1992  NA 
# 3:  Magic Johnson 1991  1 
# 4:  Magic Johnson 1992  1 
# 5:  Magic Johnson 1993  1 
# 6: Michael Jordan 1991  1 
# 7: Michael Jordan 1992  1 
# 8: Michael Jordan 1993  1 

o utilizzando dplyr

library(dplyr) 
ALLSTARS %>% 
    mutate(allstars = 1L) %>% 
    right_join(., season) 
# firstname lastname year allstars 
# 1 Michael Jordan 1991  1 
# 2 Michael Jordan 1992  1 
# 3 Michael Jordan 1993  1 
# 4  Magic Johnson 1991  1 
# 5  Magic Johnson 1992  1 
# 6  Magic Johnson 1993  1 
# 7  Larry  Bird 1992  NA 
# 8  Larry  Bird 1992  NA 
+0

@ David, grazie mille! Il mio esempio è in qualche modo fuorviante. Stai facendo riferimento nel tuo esempio alla colonna 'allstars' o alla tabella' ALLSTARS' –

+0

OK, fammi modificare per la tua modifica. Ora è meglio? –

+0

usando il primo consiglio che ottengo: 'Errore in Bmerge (i <- shallow (i), x, leftcols, rightcols, io <- haskey (i),: x.'firstname 'è una colonna di caratteri che viene unita a i .'anno 'che è di tipo' intero '. Le colonne di caratteri devono unirsi a colonne fattore o carattere. ' –

2

In base R:

ALLSTARS$allstars <- 1L 
newdf <- merge(season, ALLSTARS, by=c('firstname', 'lastname', 'year'), all.x=TRUE) 
newdf$allstars[is.na(newdf$allstars)] <- 0L 
newdf 

O uno che mi piace per un approccio diverso:

season$allstars <- (apply(season, 1, function(x) paste(x, collapse='')) %in% 
apply(ALLSTARS, 1, function(x) paste(x, collapse='')))+0L 
# 
# firstname lastname year allstars 
# 1 Michael Jordan 1991  1 
# 2 Michael Jordan 1992  1 
# 3 Michael Jordan 1993  1 
# 4  Magic Johnson 1991  1 
# 5  Magic Johnson 1992  1 
# 6  Magic Johnson 1993  1 
# 7  Larry  Bird 1992  0 
# 8  Larry  Bird 1992  0 
Problemi correlati