Pytanie Agregowanie według unikalnego identyfikatora i łączenie powiązanych wartości w łańcuch [duplikat]


To pytanie już zawiera odpowiedź:

Mam potrzebę, którą mogę sobie wyobrazić aggregate lub reshape, ale nie mogę się dowiedzieć.

Mam listę nazwisk (brand) oraz towarzyszący mu numer identyfikacyjny (id). Te dane mają długą formę, więc nazwy mogą mieć wiele identyfikatorów. Chciałbym usunąć duplikat według nazwy (brand) i połączyć wiele możliwych idjest w ciąg znaków oddzielony komentarzem.

Na przykład:

brand            id 
RadioShack       2308
Rag & Bone       4466
Ragu             1830
Ragu             4518
Ralph Lauren     1638
Ralph Lauren     2719
Ralph Lauren     2720
Ralph Lauren     2721
Ralph Lauren     2722 

powinno stać się:

RadioShack       2308
Rag & Bone       4466
Ragu             1830,4518
Ralph Lauren     1638,2719,2720,2721,2722

Jak to osiągnąć?


44
2018-05-16 20:08


pochodzenie


W pożądanym wyniku "Ragu" nie powinien pojawić się dwa razy, prawda? - Frank
Czy dla każdej marki chcesz uzyskać wynik list identyfikatorów, lub pojedynczy ciąg połączony ze sobą? - Ricardo Saporta


Odpowiedzi:


Nazwijmy twoją data.frame DF

> aggregate(id ~ brand, data = DF, c)
         brand                           id
1   RadioShack                         2308
2   Rag & Bone                         4466
3         Ragu                   1830, 4518
4 Ralph Lauren 1638, 2719, 2720, 2721, 2722

Inna alternatywa za pomocą aggregate jest:

result <- aggregate(id ~ brand, data = DF, paste, collapse = ",")

Daje to ten sam rezultat i teraz id nie jest list już. Dzięki komentarzowi @Frank. Aby zobaczyć class każdej kolumny spróbuj:

> sapply(result, class)
      brand          id 
   "factor" "character"

Jak wspomniano przez @DavidArenburg w komentarzach, inną alternatywą jest użycie toString funkcjonować:

aggregate(id ~ brand, data = DF, toString)

52
2018-05-16 20:12



Bardzo dziwnie, R nie pozwala mi wyprowadzać tych danych.frame ... Myślę, że ponieważ id to lista. Jak eksportować do pliku CSV? - roody
@Jilber klasa twojej kolumny wyjściowej "id" powinna być "znakiem" (nie listą), tak myślę, ponieważ OP chce wyeksportować ramkę danych. - Frank
+1. Podoba mi się to rozwiązanie, tak jak jest na własny użytek. Myślę, że możesz chcieć to zmienić aggregate(id~brand,paste,collapse=",",data=df) lub podobne na pytanie OP. - Frank
Warte wspomnienia aggregate(id ~ brand, DF, toString) zbyt prawdopodobnie - David Arenburg
Co się stanie, jeśli chcę zrobić to samo, ale tylko dla określonej wartości ?. Mam na myśli, w twoim przykładzie tylko z id==2308. - Henry Navarro


Ładnie czysta jedna linia w data.table

library(data.table)
setDT(DF)

DWIE OPCJE:

wyniki w postaci listy

DF[ , .(id = list(id)), by = brand]
          brand                       id
1:   RadioShack                     2308
2:   Rag & Bone                     4466
3:         Ragu                1830,4518
4: Ralph Lauren 1638,2719,2720,2721,2722
> 

wyniki jako ciąg znaków

DF[ , .(id = paste(id, collapse=",")), by = brand]
          brand                       id
1:   RadioShack                     2308
2:   Rag & Bone                     4466
3:         Ragu                1830,4518
4: Ralph Lauren 1638,2719,2720,2721,2722

Uwaga

Mimo że oba wyniki zjawić się to samo (czyli kiedy je drukujesz, wyglądają identycznie), w rzeczywistości są bardzo różne i pozwalają na inną funkcjonalność.

Mianowicie, użycie opcji listy (pierwszej) pozwala następnie wykonywać funkcje na orignalu ids.

Ta ostatnia pozwoli na łatwiejsze wyświetlanie informacji (w tym eksportowanie do CSV lub excel), ale operować na idto będzie wymagało odłożenia ich z powrotem.


33
2018-05-16 21:09



Dzięki! list (lista (id)) działa, ale dlaczego? - LauriK
@LauriK, list(list(id)) jest taka sama jak pierwsza opcja w odpowiedzi. Jedyna różnica polega na tym, że nazwa na liście jest jawnie podana, czy nie. Outter list, data.table przełożą się na znaczenie "kolumna" (jak wszystkie dane. tabele i data.frames są tak naprawdę tylko listą kolumn). Wewnętrzny list wskazuje, że wartość w każdej komórce będzie listą - Ricardo Saporta


Lub za pomocą dplyr:

library(dplyr)
DF %>%
  group_by(brand) %>%
  summarise(id = paste(id, collapse = ","))

Gdzie DF to nazwa twojego data.frame.


17
2018-05-22 12:39



Spowoduje to, że kolumny podsumowane będą ciągami oddzielanymi przecinkami. Nie wektor ... - sriharsha KB
Nie, tak jak w innych odpowiedziach, wynikiem jest data.frame, z wektorem o nazwie id klasy character zawierające ciągi id, oddzielone przecinkami zgodnie z życzeniem w pytaniu. is.vector(DF$id) zwraca TRUE. Jeśli masz pytanie dotyczące tego podejścia, rozważ umieszczenie go jako nowego pytania. - Sam Firke
biblioteka (dplyr) DFNowy ​​<-DF%>% group_by (marka)%>% summary (id = unique (lista (id))) To działało dla mnie - sriharsha KB


Oto informacje w bazie R:

myby <- by(df$id,df$brand,function(x)paste(x,collapse=","))

Formatowanie obiektów "według" jest dziwne. Możesz wziąć data.frame(id=c(myby)) a marki staną się rownames:

#                                    id
# RadioShack                       2308
# Rag & Bone                       4466
# Ragu                        1830,4518
# Ralph Lauren 1638,2719,2720,2721,2722

Alternatywnie, jeśli załadujesz plik data.table pakiet, to zadziała:

dt <- data.table(df)
dt[,paste(id,collapse=","),by=brand]
#           brand                       V1
# 1:   RadioShack                     2308
# 2:   Rag & Bone                     4466
# 3:         Ragu                1830,4518
# 4: Ralph Lauren 1638,2719,2720,2721,2722

9
2018-05-16 20:17