2014-11-27 18 views
5

Ho due frame di dati che hanno alcune colonne con lo stesso nome e altre con nomi diversi. I frame di dati sembrano qualcosa di simile:R - unione/unione di colonne con lo stesso nome ma dati incompleti

df1 
     ID hello world hockey soccer 
    1 1 NA NA  7  4 
    2 2 NA NA  2  5 
    3 3 10  8  8  23 
    4 4  4 17  5  12 
    5 5 NA NA  3  43 

df2  
     ID hello world football baseball 
    1 1  2  3  43  6 
    2 2  5  1  24  32 
    3 3 NA NA  2  23 
    4 4 NA NA  5  15 
    5 5  9  7  12  23 

Come si può vedere, in 2 delle colonne condivise ("ciao" e "mondo"), alcuni dei dati è in uno dei frame di dati e il resto è nell'altra.

Quello che sto cercando di fare è (1) unire i 2 frame di dati con "id", (2) combinare tutti i dati delle colonne "hello" e "world" in entrambi i frame nella colonna 1 "hello" e 1 colonna "mondo" e (3) hanno il riquadro dati finale contengono anche tutte le altre colonne nei 2 fotogrammi originali ("hockey", "calcio", "calcio", "baseball"). Quindi, voglio il risultato finale sia questo:

ID hello world hockey soccer football baseball 
1 1  2  3  7  4  43  6 
2 2  5  3  2  5  24  32 
3 3 10  8  8  23   2  23 
4 4  4 17  5  12   5  15 
5 5  9  7  3  43  12  23 

Sono abbastanza nuovo a R quindi l'unica codici che ho provato sono variazioni su merge e ho provato la risposta che ho trovato qui, che era basato su una domanda simile: R: merging copies of the same variable. Tuttavia, i miei set di dati sono in realtà molto più grandi di quello che sto mostrando qui (ci sono circa 20 colonne corrispondenti (come "ciao" e "mondo") e 100 di quelli non corrispondenti (come "hockey" e "calcio")) quindi sto cercando qualcosa che non mi imponga di scriverli tutti manualmente.

Qualche idea se questo può essere fatto? Mi dispiace che non posso fornire un campione dei miei sforzi, ma io davvero non so da dove cominciare inoltre:

mydata <- merge(df1, df2, by=c("ID"), all = TRUE) 

per riprodurre il frame di dati:

df1 <- structure(list(ID = c(1L, 2L, 3L, 4L, 5L), hellow = c(2, 5, NA, NA, 9), world = c(3, 1, NA, NA, 7), football = c(43, 24, 2, 5, 12), baseball = c(6, 32, 23, 15, 23)), .Names = c("ID", "hello", "world", "football", "baseball"), class = "data.frame", row.names = c(NA, -5L)) 
df2 <- structure(list(ID = c(1L, 2L, 3L, 4L, 5L), hellow = c(NA, NA, 10, 4, NA), world = c(NA, NA, 8, 17, NA), hockey = c(7, 2, 8, 5, 3), soccer = c(4, 5, 23, 12, 43)), .Names = c("ID", "hello", "world", "hockey", "soccer"), class = "data.frame", row.names = c(NA, -5L)) 
+0

E' sempre il caso che se il valore è 'NA' in" df1 "avrebbe un valore in" df2 "(e viceversa)? – A5C1D2H2I1M1N2O1R2T1

+0

Sì, è sempre così. – abclist19

risposta

5

Ecco un approccio che coinvolge i dati melt, unendo i dati fusi e utilizzando dcast per tornare a un modulo ampio. Ho aggiunto commenti per aiutare a capire cosa sta succedendo.

## Required packages 
library(data.table) 
library(reshape2) 

dcast.data.table(
    merge(
    ## melt the first data.frame and set the key as ID and variable 
    setkey(melt(as.data.table(df1), id.vars = "ID"), ID, variable), 
    ## melt the second data.frame 
    melt(as.data.table(df2), id.vars = "ID"), 
    ## you'll have 2 value columns... 
    all = TRUE)[, value := ifelse(
     ## ... combine them into 1 with ifelse 
     is.na(value.x), value.y, value.x)], 
    ## This is your reshaping formula 
    ID ~ variable, value.var = "value") 
# ID hello world football baseball hockey soccer 
# 1: 1  2  3  43  6  7  4 
# 2: 2  5  1  24  32  2  5 
# 3: 3 10  8  2  23  8  23 
# 4: 4  4 17  5  15  5  12 
# 5: 5  9  7  12  23  3  43 
+0

Ciò funziona perfettamente; Grazie! – abclist19

+0

Una domanda: i valori sembrano uscire non numerici. C'è un modo per farlo e tenerli numerici? – abclist19

+0

sì, ci sono colonne con colonne di caratteri nei miei dati reali ma non nelle colonne che stavo riscontrando problemi di fusione. Tutte le colonne che sono state sciolte sembrano essere valori di carattere ora. In qualche modo intorno a questo? – abclist19

2

Ecco un altro data.table approccio utilizzando merge binario

library(data.table) 
setkey(setDT(df1), ID) ; setkey(setDT(df2), ID) # Converting to data.table objects and setting keys 
df1 <- df1[df2][, `:=`(i.hello = NULL, i.world = NULL)] # Full left join 
df1[df2[complete.cases(df2)], `:=`(hello = i.hello, world = i.world)][] # Joining only on non-missing values 
# ID hello world football baseball hockey soccer 
# 1: 1  2  3  43  6  7  4 
# 2: 2  5  1  24  32  2  5 
# 3: 3 10  8  2  23  8  23 
# 4: 4  4 17  5  15  5  12 
# 5: 5  9  7  12  23  3  43 
2

@ risposta s' Ananda-Mahto è più elegante, ma qui è il mio suggerimento:

library(reshape2) 
df1=melt(df1,id='ID',na.rm=TRUE) 
df2=melt(df2,id='ID',na.rm=TRUE) 
DF=rbind(df1,df2) 
# Not needeed, added na.rm=TRUE based on @ananda-mahto's valid comment 
# DF<-DF[!is.na(DF$value),] 
dcast(DF,ID~variable,value.var='value') 
+0

Grazie per il tuo commento, ho aggiornato la mia risposta per incorporarla. Il tuo è ancora più elegante :) – Nikos

Problemi correlati