2013-04-05 24 views
6

Mam dwie ramki danych. Jeden (df1) zawiera wszystkie kolumny i wiersze będące przedmiotem zainteresowania, ale zawiera brakujące obserwacje. Drugi (df2) zawiera wartości, które mają być użyte zamiast brakujących obserwacji, i zawiera tylko kolumny i wiersze, dla których co najmniej jeden NA był obecny w df1. Chciałbym połączyć oba zestawy danych w jakiś sposób, aby uzyskać desired.result.scalanie ramek danych w celu wyeliminowania brakujących obserwacji

Wydaje się, że to bardzo prosty problem do rozwiązania, ale rysuję puste miejsce. Nie mogę uzyskać merge do pracy. Może mógłbym napisać zagnieżdżony for-loops, ale jeszcze tego nie zrobiłem. Próbowałem też kilka razy aggregate. Trochę się boję, aby opublikować to pytanie, obawiając się, że moja karta R może zostać unieważniona. Przepraszam, jeśli to duplikat. Wyszukiwałem tutaj i w Google dość intensywnie. Dziękuję za radę. Preferowane jest rozwiązanie w bazie R.

df1 = read.table(text = " 
    county year1 year2 year3 
    aa  10 20 30 
    bb  1 NA 3 
    cc  5 10 NA 
    dd 100 NA 200 
", sep = "", header = TRUE) 

df2 = read.table(text = " 
    county year2 year3 
    bb  2 NA 
    cc  NA 15 
    dd 150 NA 
", sep = "", header = TRUE) 

desired.result = read.table(text = " 
    county year1 year2 year3 
    aa  10 20 30 
    bb  1  2 3 
    cc  5 10 15 
    dd 100 150 200 
", sep = "", header = TRUE) 

Odpowiedz

9

aggregate można to zrobić:

aggregate(. ~ county, 
      data=merge(df1, df2, all=TRUE), # Merged data, including NAs 
      na.action=na.pass,    # Aggregate rows with missing values... 
      FUN=sum, na.rm=TRUE)   # ...but instruct "sum" to ignore them. 
## county year2 year3 year1 
## 1  aa 20 30 10 
## 2  bb  2  3  1 
## 3  cc 10 15  5 
## 4  dd 150 200 100 
+1

'FUN = Filter, f = Negate (is.na)' byłaby inna opcja dla funkcji (by zachować duplikaty, co nie powinno się zdarzyć i tak, jeśli specyfikacja OP są poprawne) – mnel

+0

Och, to chłodny. Dobra robota. – Aaron

+0

Doskonały - doskonały przykład tego, jak baza R ma wiele naprawdę schludnych i łatwo interpretowalnych funkcji, które często są pomijane. – thelatemail

2

to zrobi:

m <- merge(df1, df2, by="county", all=TRUE) 

dotx <- m[,grepl("\\.x",names(m))] 

doty <- m[,grepl("\\.y",names(m))] 

dotx[is.na(dotx)] <- doty[is.na(dotx)] 

names(dotx) <- sapply(strsplit(names(dotx),"\\."), `[`, 1) 

result <- cbind(m[,!grepl("\\.x",names(m)) & !grepl("\\.y",names(m))], dotx) 

Kontrola:

> result 
    county year1 year2 year3 
1  aa 10 20 30 
2  bb  1  2  3 
3  cc  5 10 15 
4  dd 100 150 200 
2

Inną opcją unsing reshape2 i pracy w długim format:

library(reshape2) 
## reshape to long format 
df1.m <- melt(df1) 
df2.m <- melt(df2) 
## get common values 
idx <- df1.m$county %in% df2.m$county & 
     df1.m$variable%in% df2.m$variable 
## replace NA values 
df1.m[idx,]$value <- ifelse(is.na(df1.m[idx,]$value), 
          df2.m$value , 
          df1.m[idx,]$value) 
## get the wide format 
dcast(data=df1.m,county~variable) 

    county year1 year2 year3 
1  aa 10 20 30 
2  bb  1  2  3 
3  cc  5 10 15 
4  dd 100 150 200 
+0

Twoja odpowiedź jest dość ogólna. Na przykład nadal działa, jeśli zmienię 10 na NA dla hrabstwa aa w roku1 i usuń rok3 z df2. –

+0

@MarkMiller tak, ponieważ czerpie korzyści z długiego formatu, który wykorzystuje tylko hrabstwo jako id (klucz), inne kolumny są po prostu zmiennymi. – agstudy

Powiązane problemy