2016-07-19 7 views
4

Вот мой вопрос:Как объединить и суммировать два кадры данных

df1 <- data.frame(x = 1:5, y = 2:6, z = 3:7) 
rownames(df1) <- LETTERS[1:5] 
df1 
    x y z 
A 1 2 3 
B 2 3 4 
C 3 4 5 
D 4 5 6 
E 5 6 7 

df2 <- data.frame(x = 1:5, y = 2:6, z = 3:7) 
rownames(df2) <- LETTERS[3:7] 
df2 
    x y z 
C 1 2 3 
D 2 3 4 
E 3 4 5 
F 4 5 6 
G 5 6 7 

, что я хотел это:

x y z 
A 1 2 3 
B 2 3 4 
C 4 6 8 
D 6 8 10 
E 8 10 12 
F 4 5 6 
G 5 6 7 

где были добавлены дублированные строки вверх по той же самой переменной.

+0

Если имена строк были представлены как разные атрибуты в наборах данных, это сработает? – Sevyns

+0

Я не уверен, почему этот вопрос был отмечен как дублированный @akrun. Это совершенно разные проблемы! –

+0

Хорошо, открыл. – akrun

ответ

4

С dplyr,

library(dplyr) 

# add rownames as a column in each data.frame and bind rows 
bind_rows(df1 %>% add_rownames(), 
      df2 %>% add_rownames()) %>% 
    # evaluate following calls for each value in the rowname column 
    group_by(rowname) %>% 
    # add all non-grouping variables 
    summarise_all(sum) 

## # A tibble: 7 x 4 
## rowname  x  y  z 
##  <chr> <int> <int> <int> 
## 1  A  1  2  3 
## 2  B  2  3  4 
## 3  C  4  6  8 
## 4  D  6  8 10 
## 5  E  8 10 12 
## 6  F  4  5  6 
## 7  G  5  6  7 
7

С:

# create a new variable from the rownames 
df1$rn <- rownames(df1) 
df2$rn <- rownames(df2) 

# bind the two dataframes together by row and aggregate 
res <- aggregate(cbind(x,y,z) ~ rn, rbind(df1,df2), sum) 
# or (thx to @alistaire for reminding me): 
res <- aggregate(. ~ rn, rbind(df1,df2), sum) 

# assign the rownames again 
rownames(res) <- res$rn 

# get rid of the 'rn' column 
res <- res[, -1] 

вы получите:

> res 
    x y z 
A 1 2 3 
B 2 3 4 
C 4 6 8 
D 6 8 10 
E 8 10 12 
F 4 5 6 
G 5 6 7 
+0

Любопытный, я никогда не использовал 'cbind' в контексте формулы. '.' имеет для меня больше смысла, чем' cbind (x, y, z) '(я вроде ожидал, что это будет' + '), но последнее может быть действительно полезным ... – alistaire

+1

@alistaire' cbind' is особенно полезно, когда вы не хотите применять агрегирующую функцию ко всем негрупповым столбцам (хотя я должен признать, что я забыл о опции '.' ;-)) – Jaap

2

Это может понадобиться teaking, чтобы получить логику rownames работать на более, например:

dfr <-rbind(df1,df2) 
do.call(rbind, lapply(split(dfr, sapply(rownames(dfr),substr,1,1)), colSums)) 
    x y z 
A 1 2 3 
B 2 3 4 
C 4 6 8 
D 6 8 10 
E 8 10 12 
F 4 5 6 
G 5 6 7 

Если все имена розеров можно считать альфа-символами, то решение gsub должно быть простым.

2

Альтернативой является расплавление данных и их литье. Сначала мы установили имена строк в последнем столбце обоих данных кадров благодаря @Procrastinatus Maximus

df1$rn <- rownames(df1) 
df2$rn <- rownames(df2) 

Затем растопить данные на основе имени

melt(list(df1, df2), id.vars = "rn") 

Затем мы используем dcast с MGET функции который используется для одновременного извлечения нескольких переменных.

mydf<- dcast(melt(mget(ls(pattern = "df\\d+")), id.vars = "rn"), 
     rn ~ variable, value.var = "value", fun.aggregate = sum) 

rownames(mydf) <- mydf$rn 

# get rid of the 'rn' column 
mydf <- mydf[, -1] 

> mydf 
# x y z 
#A 1 2 3 
#B 2 3 4 
#C 4 6 8 
#D 6 8 10 
#E 8 10 12 
#F 4 5 6 
#G 5 6 7