Подтвердить что ты не робот

Сортировка таблицы данных с определенным порядком значений

Вот краткая таблица данных:

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

Я хотел бы сортировать таблицу данных в порядке возрастания на 3 столбца: Tag1, Tag2 и Date. Я тестировал:

> 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

Однако, я хотел бы отсортировать таблицу данных следующим образом:

> 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

В частности, дублированные значения для Tag1 или Tag1 должны быть расположены один ниже другого (например: 6219 для Tag1 и 252863 для Tag2). Как я могу это сделать?

ИЗМЕНИТЬ

Предлагаемые решения работают для краткой таблицы данных (например, таблица данных выше). Вот более длинная версия:

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

Вот ожидаемый результат (т.е. data.table "After" ). В частности, таблица данных "После" должна учитывать два условия:

1) строки сортируются по дате в порядке возрастания

2) дублированные значения для Tag1 или Tag1 расположены один ниже другого (в конечном итоге не требуется в порядке возрастания)

Все повторяющиеся значения для Tag1 и Tag2 имеют желтый цвет.

введите описание изображения здесь

4b9b3361

Ответ 1

Старый порядок

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

Новый заказ
Сортировка столбца Date в порядке убывания, затем сортировка Tag1 по возрастанию, сгруппированная по 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

Решение @akrun в комментариях нарушает структуру данных. Вот сравнение. Посмотрите на № 4: 6219 должно иметь 252857 вместо 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

Ответ 2

Данные в примере уже отсортированы, поэтому здесь представлена ​​сокращенная версия в несортированном порядке, чтобы проиллюстрировать изменение порядка сортировки.

> 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

Используйте order для создания новой таблицы данных в определенном порядке сортировки. Функция заказа принимает одно поле или несколько полей для сортировки в указанном порядке.

# 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

Чтобы переупорядочить таблицу данных на месте, используйте функцию setorder.

setorder (DT, Tag1, Tag2, Date)

Если вы хотите сортировать по убыванию, используйте префикс - для имен полей.

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

Ответ 3

В обновлении вопроса OP указывала, что предыдущие ответы (включая принятый ответ) не работают для более длинного набора данных. Используя новые данные после редактирования вопроса, мы можем сортировать вот так:

Трюк заключается в том, чтобы начать с таблицы, упорядоченной по дате, затем тегов в порядке возрастания (исходные данные в OP уже находятся в этом состоянии, но для общности я начинаю, чтобы данные упорядочивались по setkey(DT, asDate, Tag1, Tag2)). Затем укажите различные значения tag2 в порядке их появления и сортировки по этим номерам групп (следующие две строки). Это позволит убедиться, что идентичные значения tag2 следуют друг за другом, не нарушая порядок таблицы. Затем сделайте то же самое для 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

Примечания

Это отлично работает с образцами данных. Однако слово предостережения. Нет никакой гарантии, что решение существует даже для всех возможных данных (либо с помощью этого метода, либо любым способом), особенно если повторные теги составляют большую часть всех тегов. Рассмотрим, например, следующие столбцы, в которых невозможно упорядочить строки таким образом, чтобы одинаковые буквы всегда отображались последовательно в обоих столбцах одновременно:

 a b
 a c
 b a
 b c
 c a
 c b