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

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

DT <-data.frame(avar = c(1,4,3,1), bvar = c("a","f","s","b"), cvar = c(3,4,5,2))

sort1 <-c("avar", "cvar")
sort2 <-c("avar", "bvar")
sorting <-list(sort1,sort2)
DT2<-list()

for (i in 1:2) {
  sorter<- sorting[[i]]
   #THE FOLLOWING SOLUTION WORKS!!!
   DT2[[i]] <- DT[do.call(order,DT[as.character(sorting[[i]])]),]       
}

Под сортировкой по c("avar", "cvar") я подразумеваю, что данные сначала должны быть отсортированы по avar и (если есть два одинаковых значения avar) затем по cvar. Другими словами, результатом сортировки по этому вектору должен быть только один отсортированный фрейм данных (а не список). То же самое с сортировкой по c("avar", "bvar"). Выше «ps1» обозначает одно из предложенных решений. Это дает мне DT2[[1]], который представляет собой список из двух кадров данных. это не то, что мне нужно. DT2 должен быть списком из двух кадров данных. DT2[[1]] должен быть одним фреймом данных.

Я также хочу подчеркнуть, что мне нужно, чтобы эта сортировка происходила через цикл, а не через передачу списка («сортировка») команде. Другими словами, первая итерация должна сортировать базу данных по первому элементу списка сортировки, который является векторным «сортировщиком» в моем коде. В реальном приложении данные в разных итерациях не являются одним и тем же набором данных.

После первого цикла DT2[[1]] следует отсортировать следующим образом:

avar  bvar  cvar
1     b     2
1     a     3
3     s     5
4     f     4    

после второго цикла DT2[[2]] следует отсортировать как:

avar  bvar  cvar
1     a     3
1     b     2
3     s     5
4     f     4    

В реальной жизни у меня также может быть другое количество столбцов сортировки в разных итерациях.

Что касается предлагаемых решений, использующих функцию «карта»: у меня загружены некоторые геопространственные пакеты (mapproj, пятьдесятстатер, геофасет), поэтому функция «карта» не работает должным образом, если я не выгружаю эти пакеты. Есть ли способ квалифицироваться для использования встроенной функции «карты», а не функции геопространственной карты?

Спасибо за помощь!

Приведенный вами пример кода не является допустимым кодом R. Например, sorting <-(sort1,sort2) выдаст ошибку. То же самое для for (i = 1:2). Это может свидетельствовать о наличии более глубоких проблем с общим синтаксисом R. Возможно, вам нужно сделать шаг назад и сначала ознакомиться с основами R; вы можете найти много бесплатных материалов в Интернете. Хорошей отправной точкой может быть Введение в R.

Maurits Evers 10.04.2019 04:40

Спасибо. Поправил синтаксис в посте.

Edith 10.04.2019 04:47

Спасибо. Исправил и это. Это сильно упрощенная версия 5000-строчного кода. извините за опечатки.

Edith 10.04.2019 04:56
«Есть ли способ квалифицироваться для использования встроенной функции «карты», а не функции геопространственной карты?» Просто добавьте префикс purrr::map.
Maurits Evers 10.04.2019 23:51
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
330
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Используя базу R, мы можем применить order к выбранным столбцам в sorting, используя do.call. Мы используем lapply, чтобы получить список фреймов данных

lapply(sorting, function(x) DT[do.call(order, DT[x]), ])


#[[1]]
#  avar bvar cvar
#4    1    b    2
#1    1    a    3
#3    3    s    5
#2    4    f    4

#[[2]]
#  avar bvar cvar
#1    1    a    3
#4    1    b    2
#3    3    s    5
#2    4    f    4

Спасибо. Я отредактировал свой исходный пост (добавив последние три абзаца) о том, почему предлагаемые решения не работают.

Edith 10.04.2019 16:34

@Edith Я не использовал ни одну функцию map в своем ответе, но для остальных вы можете сделать packageName::functionName, чтобы явно использовать этот пакет. Например, purrr::map

Ronak Shah 10.04.2019 16:46

Когда я использую ваше решение (lapply(sorting[[1]], function(x) DT[do.call(order, DT[x]),]), я получаю вывод, который представляет собой список: первый элемент отсортирован по данным по avar, а второй элемент — это данные, отсортированные по cvar.Второй абзац в моем отредактированном посте объясняет, что я хочу вместо этого.

Edith 10.04.2019 16:51

@Edith Я получаю тот же ожидаемый результат, что и в вашем посте. DT2 <- lapply(sorting, function(x) DT[do.call(order, DT[x]), ]). DT2[[1]] и DT[[2]] — это два фрейма данных, как показано на рисунке.

Ronak Shah 10.04.2019 16:54

Когда я использую наше решение, DT2[[1]] представляет собой список из двух элементов — дата, отсортированная по avar и cvar соответственно. Я отредактирую код, чтобы показать, как именно я добавил эту строку.

Edith 10.04.2019 17:25

@ Эдит, тебе здесь не нужен цикл for. Если вы используете мое решение как есть, вы заметите, что DT2[[1]] — это один фрейм данных, отсортированный по sorting[[1]], а DT2[[2]] — другой фрейм данных, отсортированный по sorting[[2]], и, насколько я могу судить после прочтения вашего поста, это то, что вам нужно.

Ronak Shah 11.04.2019 01:49

Спасибо. В этой упрощенной настройке команда может дать тот же результат, что и цикл, но в реальном коде набор данных на каждой итерации не является одним и тем же набором данных. Это разные наборы данных с разным количеством записей и столбцов. Поэтому мне действительно нужно иметь решение, которое работает через цикл. Кроме того, ваше решение не дает мне DT2[[1]] в качестве кадра данных. он дает мне DT2[[1]], который представляет собой список из двух фреймов данных, и DT2[[2]], который также является списком из двух фреймов данных. Вы можете видеть в коде из поста, как именно это у меня есть. Пожалуйста, не стесняйтесь исправить, если неправильно.

Edith 11.04.2019 02:12

@Edith, как я упоминал ранее, вам не нужно использовать цикл for, чтобы применить это решение. Если вы примените решение lapply в цикле for, вы получите неправильные результаты. Можешь просто DT2 <- lapply(sorting, function(x) DT[do.call(order, DT[x]), ])?

Ronak Shah 11.04.2019 02:16

(1) Нет, не могу. Я абсолютно не могу сделать это вне цикла. В первой итерации цикла DT имеет 11000 строк и 23 столбца. Во второй итерации он имеет 202 строки и 22 столбца. Несмотря на то, что у него такое же имя, это не тот же набор данных. (2) Если я выполняю ваше решение вне цикла, например так: DT2 <- lapply(sorting, function(x) DT[do.call(order, DT[x]), ]), я получаю DT2, который представляет собой список из 2 шт. каждый элемент представляет собой список из 2 кадров данных. Итак, я получаю 4 кадра данных. Это не то, что мне нужно. Я не думаю, что это зависит от среды, но рад оказаться неправым.

Edith 11.04.2019 03:13

Решение dplyr+purrr

library(purrr)
library(dplyr)
map(sorting, ~arrange(DT, !!!syms(.x)))
#[[1]]
#  avar bvar cvar
#1    1    b    2
#2    1    a    3
#3    3    s    5
#4    4    f    4
#
#[[2]]
#  avar bvar cvar
#1    1    a    3
#2    1    b    2
#3    3    s    5
#4    4    f    4

Спасибо. Я отредактировал свой исходный пост (добавив последние три абзаца) о том, почему предлагаемые решения не работают.

Edith 10.04.2019 16:34

@Edit Используйте purrr::map вместо map.

Maurits Evers 11.04.2019 05:03

Вот метод с setorder от data.table

library(data.table)
Map(setorderv, replicate(2, copy(DT), simplify = FALSE), sorting)
#[[1]]
#  avar bvar cvar
#4    1    b    2
#1    1    a    3
#3    3    s    5
#2    4    f    4

#[[2]]
#  avar bvar cvar
#1    1    a    3
#4    1    b    2
#3    3    s    5
#2    4    f    4

Или используйте arrange_at из dplyr (без использования способа оценки)

library(tidyverse)
map(sorting, ~ DT %>%
                 arrange_at(.x))
#[[1]]
#  avar bvar cvar
#1    1    b    2
#2    1    a    3
#3    3    s    5
#4    4    f    4

#[[2]]
#  avar bvar cvar
#1    1    a    3
#2    1    b    2
#3    3    s    5
#4    4    f    4

Привет спасибо. У меня есть две проблемы, связанные с этим решением:

Edith 10.04.2019 16:04

Привет спасибо. У меня есть две проблемы, связанные с этим решением: (1) у меня также загружены некоторые геопространственные пакеты (fifitystater, geofacet, mapproj). Таким образом, похоже, что функция «карты» из этих пакетов «берет» нативную функцию карты R. Я получаю сообщение об ошибке в операторе «карта», если я не выгружаю эти геоспециальные пакеты. Есть ли способ квалифицироваться для использования встроенной функции карты, а не того, что входит в геопространственные инструменты.

Edith 10.04.2019 16:10

Проблема (2) Более непосредственно связана с этой проблемой. Когда я говорю сортировать по c("avar", "bvar"), мне не нужны два отдельных вывода. Я хочу, чтобы файл сначала сортировался по авару, а затем (если есть два или более одинаковых значения авара) по бвару. На данный момент, используя это предложенное решение, я получаю вывод, который представляет собой список: первый элемент — это данные, отсортированные по a. а второй элемент — это данные, отсортированные по b.

Edith 10.04.2019 16:11

@Edith Используйте purrr::map(sorting, ~ DT %>%, чтобы решить проблему

akrun 11.04.2019 04:33
Ответ принят как подходящий
The following solution works for me! Other proposed solutions I tried failed to sort by two variables in a given vector simultaneously.

DT <-data.frame(avar = c(1,4,3,1), bvar = c("a","f","s","b"), cvar = c(3,4,5,2))

sort1 <-c("avar", "cvar")
sort2 <-c("avar", "bvar")
sorting <-list(sort1,sort2)
DT2<-list()

for (i in 1:2) {
    #THE FOLLOWING SOLUTION WORKS!!!
    DT2[[i]] <- DT[do.call(order,DT[as.character(sorting[[i]])]),]       
}

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