У меня есть цикл, в котором на разных итерациях я хочу отсортировать фрейм данных, используя разные списки столбцов. Я могу сделать эту сортировку, когда жестко запрограммирую переменные сортировки. Однако я хочу передать имена столбцов, используя список переменных. Я не мог найти способ сделать это.
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, пятьдесятстатер, геофасет), поэтому функция «карта» не работает должным образом, если я не выгружаю эти пакеты. Есть ли способ квалифицироваться для использования встроенной функции «карты», а не функции геопространственной карты?
Спасибо за помощь!
Спасибо. Поправил синтаксис в посте.
Спасибо. Исправил и это. Это сильно упрощенная версия 5000-строчного кода. извините за опечатки.
purrr::map
.
Используя базу 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 Я не использовал ни одну функцию map
в своем ответе, но для остальных вы можете сделать packageName::functionName
, чтобы явно использовать этот пакет. Например, purrr::map
Когда я использую ваше решение (lapply(sorting[[1]], function(x) DT[do.call(order, DT[x]),]), я получаю вывод, который представляет собой список: первый элемент отсортирован по данным по avar, а второй элемент — это данные, отсортированные по cvar.Второй абзац в моем отредактированном посте объясняет, что я хочу вместо этого.
@Edith Я получаю тот же ожидаемый результат, что и в вашем посте. DT2 <- lapply(sorting, function(x) DT[do.call(order, DT[x]), ])
. DT2[[1]]
и DT[[2]]
— это два фрейма данных, как показано на рисунке.
Когда я использую наше решение, DT2[[1]] представляет собой список из двух элементов — дата, отсортированная по avar и cvar соответственно. Я отредактирую код, чтобы показать, как именно я добавил эту строку.
@ Эдит, тебе здесь не нужен цикл for
. Если вы используете мое решение как есть, вы заметите, что DT2[[1]]
— это один фрейм данных, отсортированный по sorting[[1]]
, а DT2[[2]]
— другой фрейм данных, отсортированный по sorting[[2]]
, и, насколько я могу судить после прочтения вашего поста, это то, что вам нужно.
Спасибо. В этой упрощенной настройке команда может дать тот же результат, что и цикл, но в реальном коде набор данных на каждой итерации не является одним и тем же набором данных. Это разные наборы данных с разным количеством записей и столбцов. Поэтому мне действительно нужно иметь решение, которое работает через цикл. Кроме того, ваше решение не дает мне DT2[[1]] в качестве кадра данных. он дает мне DT2[[1]], который представляет собой список из двух фреймов данных, и DT2[[2]], который также является списком из двух фреймов данных. Вы можете видеть в коде из поста, как именно это у меня есть. Пожалуйста, не стесняйтесь исправить, если неправильно.
@Edith, как я упоминал ранее, вам не нужно использовать цикл for
, чтобы применить это решение. Если вы примените решение lapply
в цикле for
, вы получите неправильные результаты. Можешь просто DT2 <- lapply(sorting, function(x) DT[do.call(order, DT[x]), ])
?
(1) Нет, не могу. Я абсолютно не могу сделать это вне цикла. В первой итерации цикла DT имеет 11000 строк и 23 столбца. Во второй итерации он имеет 202 строки и 22 столбца. Несмотря на то, что у него такое же имя, это не тот же набор данных. (2) Если я выполняю ваше решение вне цикла, например так: DT2 <- lapply(sorting, function(x) DT[do.call(order, DT[x]), ]), я получаю DT2, который представляет собой список из 2 шт. каждый элемент представляет собой список из 2 кадров данных. Итак, я получаю 4 кадра данных. Это не то, что мне нужно. Я не думаю, что это зависит от среды, но рад оказаться неправым.
Решение 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
Спасибо. Я отредактировал свой исходный пост (добавив последние три абзаца) о том, почему предлагаемые решения не работают.
@Edit Используйте purrr::map
вместо map
.
Вот метод с 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
Привет спасибо. У меня есть две проблемы, связанные с этим решением:
Привет спасибо. У меня есть две проблемы, связанные с этим решением: (1) у меня также загружены некоторые геопространственные пакеты (fifitystater, geofacet, mapproj). Таким образом, похоже, что функция «карты» из этих пакетов «берет» нативную функцию карты R. Я получаю сообщение об ошибке в операторе «карта», если я не выгружаю эти геоспециальные пакеты. Есть ли способ квалифицироваться для использования встроенной функции карты, а не того, что входит в геопространственные инструменты.
Проблема (2) Более непосредственно связана с этой проблемой. Когда я говорю сортировать по c("avar", "bvar"), мне не нужны два отдельных вывода. Я хочу, чтобы файл сначала сортировался по авару, а затем (если есть два или более одинаковых значения авара) по бвару. На данный момент, используя это предложенное решение, я получаю вывод, который представляет собой список: первый элемент — это данные, отсортированные по a. а второй элемент — это данные, отсортированные по b.
@Edith Используйте purrr::map(sorting, ~ DT %>%
, чтобы решить проблему
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]])]),]
}
Приведенный вами пример кода не является допустимым кодом R. Например,
sorting <-(sort1,sort2)
выдаст ошибку. То же самое дляfor (i = 1:2)
. Это может свидетельствовать о наличии более глубоких проблем с общим синтаксисом R. Возможно, вам нужно сделать шаг назад и сначала ознакомиться с основами R; вы можете найти много бесплатных материалов в Интернете. Хорошей отправной точкой может быть Введение в R.