2016-08-20 63 views
19

我有一個長的表單數據框,有相同的日期和人的多個條目。使用與重複標識符的行傳播

jj <- data.frame(month=rep(1:3,4), 
      student=rep(c("Amy", "Bob"), each=6), 
      A=c(9, 7, 6, 8, 6, 9, 3, 2, 1, 5, 6, 5), 
      B=c(6, 7, 8, 5, 6, 7, 5, 4, 6, 3, 1, 5)) 

我想將其轉換爲寬的形式,使之像這樣:

month Amy.A Bob.A Amy.B Bob.B 
1  
2  
3 
1 
2 
3 
1 
2 
3 
1 
2 
3 

我的問題是非常相似的this。提前

Error: Duplicate identifiers for rows (1, 4), (2, 5), (3, 6), (13, 16), (14, 17), (15, 18), (7, 10), (8, 11), (9, 12), (19, 22), (20, 23), (21, 24)

感謝:我已經使用給定的代碼的答案:

kk <- jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    spread(temp, value) 

但它提供了以下錯誤。 注意:我不想刪除多個條目。

+0

輸出沒有意義。 Bob.B'5 6 7'怎麼樣。第1個月有兩個Bob B值,'5 3'?而第二個月它是'4和2'。最後,對於3個月的'6 5'。您將這些總結爲一個值。 –

回答

14

問題是AB的兩列。如果我們可以創建一個價值列,我們可以隨意傳播數據。使用下面的代碼時,請查看jj_melt的輸出。

library(reshape2) 
jj_melt <- melt(jj, id=c("month", "student")) 
jj_spread <- dcast(jj_melt, month ~ student + variable, value.var="value", fun=sum) 
# month Amy_A Amy_B Bob_A Bob_B 
# 1  1 17 11  8  8 
# 2  2 13 13  8  5 
# 3  3 15 15  6 11 

我不會將此標記爲重複,因爲其他的問題沒有被sum總結,但data.table答案可能有一個附加參數幫助,fun=sum

library(data.table) 
dcast(setDT(jj), month ~ student, value.var=c("A", "B"), fun=sum) 
# month A_sum_Amy A_sum_Bob B_sum_Amy B_sum_Bob 
# 1:  1  17   8  11   8 
# 2:  2  13   8  13   5 
# 3:  3  15   6  15  11 

如果你想要使用tidyr解決方案,請將其與dcast結合,以sum進行彙總。

as.data.frame(jj) 
library(tidyr) 
jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    dcast(month ~ temp, fun=sum) 
# month Amy_A Amy_B Bob_A Bob_B 
# 1  1 17 11  8  8 
# 2  2 13 13  8  5 
# 3  3 15 15  6 11 

編輯

根據您的新的要求,我已經添加了一個活動列。

library(dplyr) 
jj %>% group_by(month, student) %>% 
    mutate(id=1:n()) %>% 
    melt(id=c("month", "id", "student")) %>% 
    dcast(... ~ student + variable, value.var="value") 
# month id Amy_A Amy_B Bob_A Bob_B 
# 1  1 1  9  6  3  5 
# 2  1 2  8  5  5  3 
# 3  2 1  7  7  2  4 
# 4  2 2  6  6  6  1 
# 5  3 1  6  8  1  6 
# 6  3 2  9  7  5  5 

其他解決方案也可以使用。在這裏,我增加了一個可選的表達,以安排通過活動數量最終輸出:

library(tidyr) 
jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    group_by(temp) %>% 
    mutate(id=1:n()) %>% 
    dcast(... ~ temp) %>% 
    arrange(id) 
# month id Amy_A Amy_B Bob_A Bob_B 
# 1  1 1  9  6  3  5 
# 2  2 2  7  7  2  4 
# 3  3 3  6  8  1  6 
# 4  1 4  8  5  5  3 
# 5  2 5  6  6  6  1 
# 6  3 6  9  7  5  5 

data.table語法是緊湊的,因爲它允許多個value.var列,會照顧蔓延的我們。我們可以跳過melt -> cast過程。

library(data.table) 
setDT(jj)[, activityID := rowid(student)] 
dcast(jj, ... ~ student, value.var=c("A", "B")) 
# month activityID A_Amy A_Bob B_Amy B_Bob 
# 1:  1   1  9  3  6  5 
# 2:  1   4  8  5  5  3 
# 3:  2   2  7  2  7  4 
# 4:  2   5  6  6  6  1 
# 5:  3   3  6  1  8  6 
# 6:  3   6  9  5  7  5 
+0

感謝您的回答。我不想總結。不需要算術操作。我想爲Amy創建A和B列,爲Bob創建A和B列,它們只有它們各自的值。 –

+1

如果同一月份,學生和班級有兩個值,您希望選擇哪一個? –

+0

我想都。其實我正在處理出價和問題數據,因此有多個條目。 –

10

您的回答缺少mutate id!這是僅使用dplyr打包的解決方案。

jj %>% 
    gather(variable, value, -(month:student)) %>% 
    unite(temp, student, variable) %>% 
    group_by(temp) %>% 
    mutate(id=1:n()) %>% 
    spread(temp, value) 
# A tibble: 6 x 6 
# month id Amy_A Amy_B Bob_A Bob_B 
# * <int> <int> <dbl> <dbl> <dbl> <dbl> 
# 1  1  1  9  6  3  5 
# 2  1  4  8  5  5  3 
# 3  2  2  7  7  2  4 
# 4  2  5  6  6  6  1 
# 5  3  3  6  8  1  6 
# 6  3  6  9  7  5  5 
+0

如果您不想要* id *列,只需在末尾添加'%>%select(-id)'。 – bonna

0
gather(data, key = "key", value = "value", ..., na.rm = FALSE, 
    convert = FALSE, factor_key = FALSE) 

檢查,如果你倒鍵和值。 「密鑰」是新密鑰的名稱,「值」是實際值。