2016-08-10 11 views
10

Oto krótka data.table:Sortowanie danych z tabeli aby specyficzne wartości

DT <- data.table(Tag1 = c(22,253,6219,6219,252862,252864,312786,312812), 
       Tag2 = c(22,255,6220,252857,252863,252865,251191,252863), 
       Date= as.Date(as.character(c("7/25/2008","6/15/2000","6/30/2000","9/6/2002","9/6/2002","9/6/2002","9/3/2003","9/5/2003")),format = "%m/%d/%Y")) 
DT 

    Tag1 Tag2  Date 
1:  22  22 2008-07-25 
2: 253 255 2000-06-15 
3: 6219 6220 2000-06-30 
4: 6219 252857 2002-09-06 
5: 252862 252863 2002-09-06 
6: 252864 252865 2002-09-06 
7: 312786 251191 2003-09-03 
8: 312812 252863 2003-09-05 

Chciałbym sortować data.table w kolejności rosnącej przez 3 kolumny: tag1, tag2 i datą. I badane:

> test <- DT[order(Tag1, Tag2, Date)] 
> test 
    Tag1 Tag2  Date 
1:  22  22 2008-07-25 
2: 253 255 2000-06-15 
3: 6219 6220 2000-06-30 
4: 6219 252857 2002-09-06 
5: 252862 252863 2002-09-06 
6: 252864 252865 2002-09-06 
7: 312786 251191 2003-09-03 
8: 312812 252863 2003-09-05 

Jednakże chciałbym posortować data.table następująco:

> test 
     Tag1 Tag2  Date 
    1:  22  22 2008-07-25 
    2: 253 255 2000-06-15 
    3: 6219 6220 2000-06-30 
    4: 6219 252857 2002-09-06 
    5: 252862 252863 2002-09-06 
    6: 312812 252863 2003-09-05 
    7: 252864 252865 2002-09-06 
    8: 312786 251191 2003-09-03 

W szczególności zduplikowane wartości Tag1 lub Tag1 powinny być umieszczone jeden pod drugim (na przykład: 6219 dla Tag1 i 252863 dla Tag2). Jak mogę to zrobić?

EDIT:

Proponowane rozwiązania działać przez krótki data.table (jak wyżej data.table). Tutaj jest już wersja:

DT <- data.table(Tag1 = c(252860, 252862, 312812, 252864, 252866, 252868, 252870, 318880, 252872, 252874, 252876, 252878, 252880, 252880, 252881, 252883, 
252885, 252887, 311264, 252889, 252889, 252892, 318879, 318880, 318881), Tag2 = c(252861, 252863, 252863, 252865, 252867, 252869, 252871, 252871, 252873, 
252875, 252877, 252879, 414611, 905593, 252882, 252884, 252886, 252888, 252888, 252890, 318904, 252893, 318878, 414547, 318882), Date = c("9/6/2002", 
"9/6/2002", "9/5/2003", "9/6/2002", "9/6/2002", "9/6/2002", "9/6/2002", "10/8/2003", "9/6/2002", "9/6/2002", "9/6/2002", "9/6/2002", "10/5/2004", 
"9/6/2002", "9/6/2002", "9/6/2002", "9/10/2002", "9/10/2002", "7/15/2003", "9/10/2002", "10/15/2003", "9/10/2002", "10/8/2003", "9/29/2004","10/8/2003")) 

Oto oczekiwany wynik (tj data.table „po”). W szczególności data.table „po” powinny być zgodne z dwóch warunków:

1) rzędy są klasyfikowane przez pory w porządku rosnącym

2) zduplikowane wartości Tag1 lub Tag1 są umieszczone jeden pod drugi (ostatecznie nie jest potrzebny w porządku rosnącym)

Wszystkie zduplikowane wartości dla Tag1 i Tag2 są żółte.

enter image description here

+1

Wtedy może trzeba przełamać 'order'. tj. "DT [, lapply (DT, sort)]' – akrun

+0

@Sathish To był komentarz, a nie odpowiedź. Z tego powodu nie opublikowałem tego. – akrun

+0

Jakiego rodzaju danych używasz do tego rodzaju grupowania/zamawiania? – HubertL

Odpowiedz

6

Old Order

df[order(Tag1, Tag2, Date)] 
#  Tag1 Tag2  Date 
# 1:  22  22 2008-07-25 
# 2: 253 255 2000-06-15 
# 3: 6219 6220 2000-06-30 
# 4: 6219 252857 2002-09-06 
# 5: 252862 252863 2002-09-06 
# 6: 252864 252865 2002-09-06 
# 7: 312786 251191 2003-09-03 
# 8: 312812 252863 2003-09-05 

New Order
Sortuj Date kolumny w kolejności malejącej, a następnie rodzaj Tag1 w kolejności rosnącej pogrupowane według Tag2.

setcolorder(dt1 <- df[order(-Date)][order(Tag1), .SD, by = Tag2], colnames(df)) 

dt1 
#  Tag1 Tag2  Date 
# 1:  22  22 2008-07-25 
# 2: 253 255 2000-06-15 
# 3: 6219 252857 2002-09-06 
# 4: 6219 6220 2000-06-30 
# 5: 252862 252863 2002-09-06 
# 6: 312812 252863 2003-09-05 
# 7: 252864 252865 2002-09-06 
# 8: 312786 251191 2003-09-03 

Rozwiązanie @akrun w komentarzach zakłóca strukturę danych. Oto porównanie. Spójrz na # 4: 6219 powinna mieć 252857 zamiast 251191

df[,lapply(df, sort)] 
#  Tag1 Tag2  Date 
# 1:  22  22 2000-06-15 
# 2: 253 255 2000-06-30 
# 3: 6219 6220 2002-09-06 
# 4: 6219 251191 2002-09-06 
# 5: 252862 252857 2002-09-06 
# 6: 252864 252863 2003-09-03 
# 7: 312786 252863 2003-09-05 
# 8: 312812 252865 2008-07-25 
+0

Czy możliwe jest przechowywanie wszystkich kolumn data.table, a nie tylko trzech kolumn "Tag1," Tag2 "i" Date "z funkcją' setcolorder'? Na przykład mam data.table z trzema kolumnami "Tag1, "Tag2" i "Data" oraz inne kolumny. – Nell

+0

Dlaczego data nie jest uporządkowana, gdy data w wierszu 4 (w data.table stare zamówienie) zostanie zastąpiona datą w wierszu 3 (tj. 2002-09-06 zamiast 2000-06-30 at wiersz 3 i 2000-06-30 zamiast 2002-09-06 w wierszu 4? – Nell

+0

Na przykład: 'DT <- data.table (Tag1 = c (22253 6219,6219,252862,252864,312786,312812), Tag2 = c (2225562202525857252863,252865,251191,252863), aa = c (1,5,9,6,1,1,1,3), Data = as.Data (tak jak.znak (c ("7/25/2008", "6/15/2000", "9/6/2002", "6/30/2000", "9/6/2002", "9/6/2002 "," 9/3/2003 "," 9/5/2003 ")), format ="% m /% d /% Y ")) setcolorder (test <- DT [order (Tag1, Tag2, Date) ] [, .SD, przez = Tag2], colnames (DT)) '. W takim przypadku data nie jest uporządkowana w kolejności (linia 3 i 4 w tym nowym zamówieniu) – Nell

2

Dane w tym przykładzie są już klasyfikowane więc o to skrócona wersja w celu zilustrowania niesegregowanych zmieniając porządek.

> library(data.table) 
> DT <- data.table(Tag1 = c(22,253,22,22), 
        Tag2 = c(1,255,2,2), 
        Date = as.Date(as.character(c(
       "1/1/2010","4/4/2000","3/3/2003","2/2/2000")), format = "%m/%d/%Y")) 
> DT     

    Tag1 Tag2  Date 
1: 22 1 2010-01-01 
2: 253 255 2000-04-04 
3: 22 2 2003-03-03 
4: 22 2 2000-02-02 

użytkowania order aby utworzyć nowy data.table w określonej kolejności sortowane. Funkcja porządkowania przyjmuje pojedyncze pole lub wiele pól do sortowania w określonej kolejności.

# sorts first by Tag1 then by Tag2 and finally by Date (in ascending order) 
> DT2 <- DT[order(Tag1, Tag2, Date)] 
> DT2 

    Tag1 Tag2  Date 
1: 22 1 2010-01-01 
2: 22 2 2000-02-02 
3: 22 2 2003-03-03 
4: 253 255 2000-04-04 

Aby ponownie zamówić plik data.table, należy użyć funkcji setorder.

setorder (DT, Tag1, tag2, data)

Jeśli chcesz uporządkować malejąco następnie użyć - prefiks na nazwy pól.

> DT[order(Tag1, Tag2, -Date)] 
> setorder(DT, Tag1, Tag2, -Date) 
+0

Bardzo dziękuję JasonM1 za odpowiedź. Moja surowa tabela danych jest podobna do mojej z przykładu, to jest w posortowanej kolejności. – Nell

1

W aktualizacji na pytanie OP wskazywały, że dotychczasowe odpowiedzi (w tym przyjętym odpowiedź) nie działają przez dłuższy zbioru danych. Korzystając z nowych danych po edycji pytania, możemy sortować w następujący sposób:

Sztukę rozpoczyna się od tabeli uporządkowanej według daty, a następnie znaczników, w porządku rosnącym (początkowe dane w PO są już w tym stanie, ale dla ogólność Zaczynam od upewnienia się, że dane są zamówione przez setkey(DT, asDate, Tag1, Tag2)). Następnie policz różne wartości tag2, w kolejności, w jakiej pojawiają się i sortuj według tych numerów grup (kolejne dwie linie). Zapewni to, że identyczne wartości tag2 będą się nawzajem podążać, bez naruszania porządku tabeli. Następnie wykonaj to samo dla tag1.

DT[, asDate := as.Date(Date, format = "%m/%d/%Y")] 
setkey(DT, asDate, Tag1, Tag2) 

DT[, g2 := .GRP, Tag2] 
setkey(DT, g2) 
DT[, g1 := .GRP, Tag1] 
setkey(DT, g1) 

DT[, c("g1", "g2", "asDate") := NULL][] 

     Tag1 Tag2  Date 
1: 252860 252861 9/6/2002 
2: 252862 252863 9/6/2002 
3: 312812 252863 9/5/2003 
4: 252864 252865 9/6/2002 
5: 252866 252867 9/6/2002 
6: 252868 252869 9/6/2002 
7: 252870 252871 9/6/2002 
8: 318880 252871 10/8/2003 
9: 318880 414547 9/29/2004 
10: 252872 252873 9/6/2002 
11: 252874 252875 9/6/2002 
12: 252876 252877 9/6/2002 
13: 252878 252879 9/6/2002 
14: 252880 905593 9/6/2002 
15: 252880 414611 10/5/2004 
16: 252881 252882 9/6/2002 
17: 252883 252884 9/6/2002 
18: 252885 252886 9/10/2002 
19: 252887 252888 9/10/2002 
20: 311264 252888 7/15/2003 
21: 252889 252890 9/10/2002 
22: 252889 318904 10/15/2003 
23: 252892 252893 9/10/2002 
24: 318879 318878 10/8/2003 
25: 318881 318882 10/8/2003 
     Tag1 Tag2  Date 

Uwagi

Działa to doskonale na przykładowych danych. Jednak słowo ostrzeżenia. Nie ma gwarancji, że istnieje rozwiązanie dla wszystkich możliwych danych (za pomocą tej metody lub dowolnej metody), szczególnie jeśli powtarzające się znaczniki stanowią znaczną część wszystkich znaczników. Rozważmy na przykład następujące kolumny, w której nie jest możliwe złożenie zamówienia wiersze tak, że te same litery zawsze pojawiają się kolejno w obu kolumnach jednocześnie:

a b 
a c 
b a 
b c 
c a 
c b 
+0

@Nie dodałem tę odpowiedź kilka dni temu - o ile mogę powiedzieć, że odpowiada dokładnie na twoje pytanie. Czy był problem z tą odpowiedzią, która nie działa dla Ciebie, czy rozwiązała Twój problem? – dww