2013-04-05 3 views
6

У меня есть два кадра данных. Один (df1) содержит все столбцы и строки, представляющие интерес, но содержит отсутствующие наблюдения. Другой (df2) включает значения, которые будут использоваться вместо отсутствующих наблюдений, и включает только столбцы и строки, для которых по меньшей мере один NA присутствует в df1. Я хотел бы как-то объединить два набора данных, чтобы получить desired.result.слияние кадров данных для устранения отсутствующих наблюдений

Это кажется очень простой проблемой для решения, но я рисую пробел. Я не могу получить merge для работы. Возможно, я мог писать вложенные for-loops, но пока этого не сделал. Я также попробовал aggregate несколько раз. Я немного боюсь поставить этот вопрос, опасаясь, что моя карта R может быть отозвана. Извините, если это дубликат. Я искал здесь и с Google довольно интенсивно. Спасибо за любой совет. Предпочтительным является решение в основании 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) 

ответ

9

aggregate может это сделать:

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 = Фильтр, е = Отрицание (is.na)' будет другой вариант для функции (будет держать дубликаты, которые не должны произойти в любом случае, если спецификация OP правильно) – mnel

+0

О, это круто. Отлично сработано. – Aaron

+0

Отлично - яркий пример того, как в базе R есть много действительно опрятных и легко интерпретируемых функций, которые часто игнорируются. – thelatemail

2

Это будет делать:

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) 

Проверка:

> 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

Другой вариант unsing reshape2 и работает в долгосрочной перспективе Формат:

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

Ваш ответ довольно общий. Например, он по-прежнему работает, если я изменю 10 на NA для округа aa в год1 и удалю год3 из df2. –

+0

@MarkMiller да, потому что он выигрывает от длинного формата, который использует только графство как id (ключ), другие столбцы - это просто переменные. – agstudy

Смежные вопросы