Как отсортировать фрейм данных (в базе R) по всем столбцам, не зная заранее все столбцы

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

dd <- data.frame(key1=c("NED", "LTU", "LAT", "ITA"), h=c(18, 3, 2, 59))      # Two columns.
dd <- rbind(dd, dd, dd)                                                      # Example dataframe.

# Append a random number of auxiliary columns, ak1, ak2, ...
set.seed(2024); n <- sample(4:8, size=1)                                     # Number of aux. columns.
akeys <- matrix(sample(x=c(1,2,3), size=nrow(dd) * n, replace=TRUE),
                ncol=n
               )                                                             # With random values 1..3.
colnames(akeys) <- paste0("ak", seq(n))                                      # Column names: ak1, ak2, ...

d2 <- cbind(dd, akeys)                                                       # Append n columns for sorting.
                                                                             # Assuming n = 5.
id3 <- order(d2$key1, d2$h, -d2$ak1, -d2$ak2, -d2$ak3, -d2$ak4, -d2$ak5)     # Sort all columns by name.
id4 <- order(d2[,1], d2[,2], -d2[,3], -d2[,4], -d2[,5], -d2[,6], -d2[, 7])   # Sort by column number.

Вопрос: Как отсортировать по убыванию или возрастанию фрейм данных по (выбору) всех столбцов, не зная заранее всех столбцов.

Например:

  • отсортировать фрейм данных по всем столбцам.
  • отсортируйте фрейм данных по ключу 1 (по возрастанию), а затем по последним n столбцам (по убыванию).
# Output d3
d2[id3, ]
#    key1  h ak1 ak2 ak3 ak4 ak5
# 8   ITA 59   2   1   3   3   3
# 4   ITA 59   1   2   3   1   1
# 12  ITA 59   1   2   1   1   1
# 3   LAT  2   3   2   2   1   3
# 11  LAT  2   3   1   3   2   3
# 7   LAT  2   2   1   2   1   1
# 10  LTU  3   1   3   1   1   2
# 2   LTU  3   1   2   3   1   1
# 6   LTU  3   1   2   1   2   2
# 9   NED 18   3   3   1   1   1
# 5   NED 18   1   2   3   2   2
# 1   NED 18   1   2   1   2   3

Редактировать (@jay.sf). Сортировка фрейма данных по (выбору) всех столбцов в порядке возрастания или убывания:

nc     <- ncol(d2)                                        # Number of columns in d2.
bycols <- subset(d2, select = c(key1, tail(seq(nc), n)) ) # Select columns by name and index in one line.
bysort <- c(FALSE, rep(TRUE, nc-1) )                      # Decending, asscending ...
idx    <- do.call('order',                                # New sort index.
                  c(bycols,                               # List of sort keys.
                    decreasing=list(bysort),              # Sort direction.
                    method='radix')
                   )
identical(id3, idx)
d6 <- d2[idx, ]; d6

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
160
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Использование order с do.call.

> d2[do.call('order', d2), ]
   key1  h ak1 ak2 ak3 ak4 ak5
12  ITA 59   1   2   1   1   1
4   ITA 59   1   2   3   1   1
8   ITA 59   2   1   3   3   3
7   LAT  2   2   1   2   1   1
11  LAT  2   3   1   3   2   3
3   LAT  2   3   2   2   1   3
6   LTU  3   1   2   1   2   2
2   LTU  3   1   2   3   1   1
10  LTU  3   1   3   1   1   2
1   NED 18   1   2   1   2   3
5   NED 18   1   2   3   2   2
9   NED 18   3   3   1   1   1

> d2[do.call('order', c(d2, decreasing=TRUE)), ]
   key1  h ak1 ak2 ak3 ak4 ak5
9   NED 18   3   3   1   1   1
5   NED 18   1   2   3   2   2
1   NED 18   1   2   1   2   3
10  LTU  3   1   3   1   1   2
2   LTU  3   1   2   3   1   1
6   LTU  3   1   2   1   2   2
3   LAT  2   3   2   2   1   3
11  LAT  2   3   1   3   2   3
7   LAT  2   2   1   2   1   1
8   ITA 59   2   1   3   3   3
4   ITA 59   1   2   3   1   1
12  ITA 59   1   2   1   1   1

Попробуйте добавить аргумент decreasing= для каждого столбца.

> d2[
+   do.call('order', 
+           c(d2, decreasing=list(c(FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE)),
+             method='radix')),
+ ]
   key1  h ak1 ak2 ak3 ak4 ak5
12  ITA 59   1   2   1   1   1
4   ITA 59   1   2   3   1   1
8   ITA 59   2   1   3   3   3
7   LAT  2   2   1   2   1   1
3   LAT  2   3   2   2   1   3
11  LAT  2   3   1   3   2   3
10  LTU  3   1   3   1   1   2
6   LTU  3   1   2   1   2   2
2   LTU  3   1   2   3   1   1
1   NED 18   1   2   1   2   3
5   NED 18   1   2   3   2   2
9   NED 18   3   3   1   1   1

Мое решение именно так. (Однако одинарные кавычки вам не нужны.)

Rui Barradas 22.06.2024 13:34

@RuiBarradas Я видел сбои в кодах без кавычек чаще, чем в кодах с кавычками, поэтому с тех пор я использую кавычки ;-)

jay.sf 22.06.2024 13:37

@clp, посмотрите обновление, пожалуйста.

jay.sf 22.06.2024 20:06

@clp Не зная заранее столбцов, но зная направления, почему?

jay.sf 22.06.2024 23:13

@jay.sf, мы знаем некоторые столбцы (например, key1), но не все. Я уточнил свой вопрос.

clp 22.06.2024 23:42

@clp Проверьте обновление, не уверены, соответствует ли оно вашим требованиям.

jay.sf 23.06.2024 00:06

Вы можете запустить следующий код для сортировки по всем столбцам. Обратите внимание, что сортировка осуществляется по ссылке. Обратите внимание, что это решение не основано на встроенных функциях.

data.table::setorderv(d2)

   key1  h ak1 ak2 ak3 ak4 ak5
12  ITA 59   1   2   1   1   1
4   ITA 59   1   2   3   1   1
8   ITA 59   2   1   3   3   3
7   LAT  2   2   1   2   1   1
11  LAT  2   3   1   3   2   3
3   LAT  2   3   2   2   1   3
6   LTU  3   1   2   1   2   2
2   LTU  3   1   2   3   1   1
10  LTU  3   1   3   1   1   2
1   NED 18   1   2   1   2   3
5   NED 18   1   2   3   2   2
9   NED 18   3   3   1   1   1

Обратите внимание, что эта функция имеет два аргумента для настройки способа сортировки и использования столбцов. Аргумент cols указывает используемые столбцы (по умолчанию все столбцы), а аргумент order указывает, как используется каждый столбец (в порядке возрастания или убывания); В order1 используется для увеличения, а -1 для убывания порядка, и его длина может быть равна количеству столбцов, используемых для сортировки. Чтобы отсортировать data.frame по возрастанию на основе первого столбца и по убыванию для остальных столбцов, можно использовать приведенный ниже код:

data.table::setorderv(d2, order=c(1, rep(-1, length(d2)-1)))

Если вы не ограничиваетесь только базой R, вы можете попробовать

d2 %>%
    arrange(across(everything()))

который дает

   key1  h ak1 ak2 ak3 ak4 ak5
1   ITA 59   1   2   1   1   1
2   ITA 59   1   2   3   1   1
3   ITA 59   2   1   3   3   3
4   LAT  2   2   1   2   1   1
5   LAT  2   3   1   3   2   3
6   LAT  2   3   2   2   1   3
7   LTU  3   1   2   1   2   2
8   LTU  3   1   2   3   1   1
9   LTU  3   1   3   1   1   2
10  NED 18   1   2   1   2   3
11  NED 18   1   2   3   2   2
12  NED 18   3   3   1   1   1

В Base R я сортирую подмножество исходного фрейма данных, состоящее из всех ключей, и использую полученный индекс для упорядочения исходного фрейма данных. Какова процедура в dplyr, если известен один ключ, скажем «ключ1», а остальные ключи состоят из переменного числа ak1, ak2, ..., akn, в зависимости от ввода?

clp 25.06.2024 11:20

Другие вопросы по теме