2016-08-20 16 views
19

Mam długą ramkę danych formularza, która ma wiele wpisów dla tej samej daty i osoby.Używanie rozkładówki z duplikatami identyfikatorów dla wierszy

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

Chcę, aby przekształcić go do szerokiej formie i zrobić to tak:

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

Moje pytanie jest bardzo podobny do this. Użyłem dany kod odpowiedź:

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

ale daje następujący błąd:

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)

góry dziękuję. Uwaga: Nie chcę usuwać wielu wpisów.

+0

Dane wyjściowe nie mają sensu. Jak jest Bob.B '5 6 7'. Istnieją dwie wartości Boba B dla miesiąca 1, '5 3'? A dla miesiąca 2 jest to "4 i 2". Wreszcie, dla miesiąca 3 '6 5'. Podsumowujecie je do jednej wartości. –

Odpowiedz

14

Problem dotyczy dwóch kolumn, zarówno dla A, jak i B. Jeśli możemy zrobić tę kolumnę z jedną wartością, możemy rozłożyć dane tak, jak byśmy tego chcieli. Spójrz na dane wyjściowe dla jj_melt, gdy użyjesz poniższego kodu.

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 

nie będę oznaczyć to jako duplikat, ponieważ inna kwestia nie podsumować przez sum, ale data.table odpowiedź mogłaby pomóc z jednym dodatkowym argumentem 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 

Jeśli chcesz aby użyć rozwiązania tidyr, połącz je z dcast, aby podsumować pod numerem 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 

Edit

podstawie nowych wymagań, dodałem kolumnę aktywności.

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 

Można również użyć innych rozwiązań. Tutaj dodałem opcjonalnego wyrażenia w celu ustalenia ostatecznego wyjścia, numer aktywny:

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 

Składnia data.table jest zwarty, ponieważ pozwala to na wielu value.var kolumn i zadba o rozprzestrzenianiu się za nami. Możemy wtedy pominąć proces 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

Dzięki za odpowiedź. Nie chcę sumować. Żadna operacja arytmetyczna nie jest potrzebna.Chcę utworzyć kolumny A i B dla Amy oraz kolumny A i B dla Boba, które mają po prostu odpowiednie wartości. –

+1

Jeśli istnieją dwie wartości dla tego samego miesiąca, ucznia i klasy, którą z nich chcesz wybrać? –

+0

Chcę obu. Właściwie to mam do czynienia z danymi o stawkach i zapytaniach, a zatem istnieje wiele wpisów. –

10

W twojej odpowiedzi brakowało mutacji id! Oto rozwiązanie z użyciem tylko pakietu 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

Jeśli nie chcesz kolumny * id *, po prostu dodaj '%>% select (-id)' na końcu. – bonna

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

Sprawdź czy odwrócony klucz i wartość. "Klucz" to nazwa nowego klucza, a "wartość" to rzeczywista wartość.

Powiązane problemy