Сортировка одной переменной во фрейме данных по идентификатору - PullRequest
4 голосов
/ 20 марта 2019

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

df <- structure(list(id = c(110, 110, 110, 90, 90, 90, 90, 252, 252
), var1 = c(26, 21, 54, 10, 18, 9, 16, 54, 39), var2 = c(234, 
12, 43, 32, 21, 19, 16, 34, 44)), .Names = c("id", "var1", "var2"
), row.names = c(NA, -9L), class = "data.frame")

, который выглядит следующим образом

df
   id var1 var2
1 110   26  234
2 110   21   12
3 110   54   43
4  90   10   32
5  90   18   21
6  90    9   19
7  90   16   16
8 252   54   34
9 252   39   44

Теперь я хочу отсортировать фрейм данных по var1 по вектору id.Самое простое решение, о котором я могу подумать, это использовать функцию apply, подобную этой,

> apply(df, 2, sort)
       id var1 var2
 [1,]  90    9   12
 [2,]  90   10   16
 [3,]  90   16   19
 [4,]  90   18   21
 [5,] 110   21   32
 [6,] 110   26   34
 [7,] 110   39   43
 [8,] 252   54   44
 [9,] 252   54  234

Однако, это не тот вывод, который я ищу.Правильный вывод должен быть

   id var1 var2
1 110   21   12
2 110   26  234
3 110   54   43
4  90    9   19
5  90   10   32
6  90   16   16
7  90   18   21
8 252   39   44
9 252   54   34

Группировать по id и сортировать по var1 столбец и сохранять исходный id порядок столбцов.

Любая идеякак сортировать так?

Ответы [ 5 ]

6 голосов
/ 20 марта 2019

Примечание. Как уже упоминалось Moody_Mudskipper, нет необходимости использовать tidyverse, и его также можно легко сделать с помощью базы R:

df[order(ordered(df$id, unique(df$id)), df$var1), ]

Aоднострочное tidyverse решение без каких-либо temp переменных:

library(tidyverse)
df %>% arrange(ordered(id, unique(id)), var1)
#    id var1 var2
# 1 110   26  234
# 2 110   21   12
# 3 110   54   43
# 4  90   10   32
# 5  90   18   21
# 6  90    9   19
# 7  90   16   16
# 8 252   54   34
# 9 252   39   44

Объяснение причин, по которым apply(df, 2, sort) не работает

ЧтоВы пытались сделать, это отсортировать каждый столбец независимо.apply пробегает указанное измерение (2 в этом случае, которое соответствует столбцам) и применяет функцию (sort в этом случае).

apply пытается еще больше упростить результаты, вэтот случай к матрице.Таким образом, вы получаете матрицу (, а не a data.frame), где каждый столбец сортируется независимо.Например, эта строка из вызова apply:

# [1,]  90    9   12

даже не существует в исходном data.frame.

6 голосов
/ 20 марта 2019

Другая базовая опция R с использованием order и match

df[with(df, order(match(id, unique(id)), var1, var2)), ]
#   id var1 var2
#2 110   21   12
#1 110   26  234
#3 110   54   43
#6  90    9   19
#4  90   10   32
#7  90   16   16
#5  90   18   21
#9 252   39   44
#8 252   54   34
3 голосов
/ 20 марта 2019

В базе R мы могли бы использовать split<-:

split(df,df$id) <- lapply(split(df,df$id), function(x) x[order(x$var1),] )

или, как предлагает @Markus:

split(df, df$id) <- by(df, df$id, function(x) x[order(x$var1),])

вывод в любом случае:

df
#    id var1 var2
# 1 110   21   12
# 2 110   26  234
# 3 110   54   43
# 4  90    9   19
# 5  90   10   32
# 6  90   16   16
# 7  90   18   21
# 8 252   39   44
# 9 252   54   34
3 голосов
/ 20 марта 2019

Мы можем преобразовать id в коэффициент, чтобы разделить при сохранении исходного порядка. Затем мы можем перебрать список и порядок, и снова rbind, т.е.

df$id <- factor(df$id, levels = unique(df$id))
do.call(rbind, lapply(split(df, df$id), function(i)i[order(i$var1),]))

#       id var1 var2
#110.2 110   21   12
#110.1 110   26  234
#110.3 110   54   43
#90.6   90    9   19
#90.4   90   10   32
#90.7   90   16   16
#90.5   90   18   21
#252.9 252   39   44
#252.8 252   54   34

ПРИМЕЧАНИЕ: Вы можете сбросить имена строк на rownames(new_df) <- NULL

2 голосов
/ 20 марта 2019

При следующей трубе tidyverse выводится вопрос вопроса.

library(tidyverse)

df %>%
  mutate(tmp = cumsum(c(0, diff(id) != 0))) %>%
  group_by(id) %>%
  arrange(tmp, var1) %>%
  select(-tmp)
## A tibble: 9 x 3
## Groups:   id [3]
#     id  var1  var2
#  <dbl> <dbl> <dbl>
#1   110    21    12
#2   110    26   234
#3   110    54    43
#4    90     9    19
#5    90    10    32
#6    90    16    16
#7    90    18    21
#8   252    39    44
#9   252    54    34
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...