2014-11-27 10 views
5

Mam dwie ramki danych, które mają niektóre kolumny o tych samych nazwach i inne o różnych nazwach. Ramki danych wyglądać następująco:R - scalanie/łączenie kolumn o tej samej nazwie, ale niekompletnych danych

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 

Jak widać, w 2 wspólnych kolumn („Hello” i „świata”), część danych jest w jednej z ramek danych, a reszta jest w drugiej.

Co próbuję zrobić to (1) scalić 2 ramki danych według "id", (2) połączyć wszystkie dane z kolumn "cześć" i "świat" w obu ramkach w 1 "cześć" kolumna i 1 kolumnę "świat" oraz (3) mają końcową ramkę danych zawierającą również wszystkie pozostałe kolumny w 2 oryginalnych klatkach ("hokej", "piłka nożna", "piłka nożna", "baseball"). Tak, chcę końcowy wynik będzie tak:

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 

Jestem całkiem nowe na R więc jedynym kody Próbowałem są wariacje na merge i próbowałem odpowiedź znalazłem tutaj, co było na podstawie podobnego pytania: R: merging copies of the same variable. Jednak moje zbiory danych są znacznie większe niż to, co tu pokazuję (jest około 20 dopasowanych kolumn (takich jak "cześć" i "świat") i 100 z nie pasujących do siebie (np. "Hokej" i "piłka nożna")) więc szukam czegoś, co nie wymagałoby zapisywania ich ręcznie.

Każdy pomysł, czy można to zrobić? Przykro mi, że nie może dostarczyć próbkę moich wysiłków, ale ja naprawdę nie wiem od czego zacząć oprócz:

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

do odtworzenia ramki danych:

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

Czy zawsze jest tak, że jeśli wartość "NA" w "df1" miałaby wartość w "df2" (i na odwrót)? – A5C1D2H2I1M1N2O1R2T1

+0

Tak, zawsze tak jest. – abclist19

Odpowiedz

5

Oto podejście polega na melt twoich danych, łączeniu stopionych danych i użyciu dcast, aby przywrócić je do szerokiej formy. Dodałem komentarze, aby pomóc zrozumieć, co się dzieje.

## 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

To działa idealnie; dzięki! – abclist19

+0

Jedno pytanie: wydaje się, że wartości nie są numeryczne. Czy istnieje sposób, aby to osiągnąć i zachować numeryczne? – abclist19

+0

Tak, istnieją kolumny z kolumnami znaków w moich rzeczywistych danych, ale nie w kolumnach, w których miałem problemy z łączeniem. Wszystkie kolumny, które zostały roztopione, wydają się teraz wartościami znaków. Jakikolwiek sposób obejścia tego? – abclist19

2

Oto kolejny podejście data.table użyciu binarnego seryjnej

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

@ odpowiedź Ananda-Mahto „s jest bardziej elegancki, ale tutaj jest moja propozycja:

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

Dziękuję za komentarz, zaktualizowałem swoją odpowiedź, aby to uwzględnić. Twój jest jeszcze bardziej elegancki :) – Nikos

Powiązane problemy