Группировать данные по фактору и упорядоченной позиции строки - PullRequest
2 голосов
/ 21 апреля 2020

Следующий код,

set.seed(123)
data <- runif(20) 
dummy <- as.data.frame(data)
dummy <- dummy %>% mutate(category = factor(case_when(data < 0.5 ~ 'A', 
                                    data >= 0.5  ~ 'B')))

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

        data category
1  0.2875775        A
2  0.7883051        B
3  0.4089769        A
4  0.8830174        B
5  0.9404673        B
6  0.0455565        A
7  0.5281055        B
8  0.8924190        B
9  0.5514350        B
10 0.4566147        A
. ...              ...

Моя проблема:

Я хочу создать новый столбец с именем packet, который создает новую группировку на основе категории и упорядоченной позиции в таблице. Он должен пометить первые packet_size строки каждой категории как packet_num, затем следующие packet_size строки должны быть помечены packet_num + 1 и т. Д.

Например, для packet_size = 2 первые 10 строк должны выглядеть следующим образом:

        data category packet
1  0.2875775        A      1
2  0.7883051        B      1
3  0.4089769        A      1
4  0.8830174        B      1
5  0.9404673        B      2
6  0.0455565        A      2
7  0.5281055        B      2
8  0.8924190        B      3
9  0.5514350        B      3
10 0.4566147        A      2
. ...              ...

Если я отфильтрую dummy до одного category, тогда я могу запустить следующее подмножество, которое, кажется, работает:

dummy <- dummy %>% add_column(packet=1L)
filtered_dummy <- dummy %>% filter(category=='A')

packet_size <- 2
packet_num <- 1
row_count <- 1
for (i in 1:nrow(filtered_dummy)) {
  filtered_dummy[i, "packet"] <- packet_num

  row_count <- row_count + 1
  if (row_count > packet_size) {
      packet_num <- packet_num + 1
      row_count = 1
  }
}

Но я ищу решение, которое может автоматически работать на полном наборе данных, предпочтительно с использованием решения Tidyverse (т.е. без моего l oop выше). Мои фактические данные имеют ту же форму, что и в этом примере, но составляют примерно 450000 строк x 90 столбцов с примерно 20 различными категориями в столбце категории.

Я думал о некоторой комбинации dplyr::mutate и slider::slide или даже как-то просто используя dplyr::group_by и вышеприведенный код цикла, но я не могу заставить его работать.

Ответы [ 3 ]

1 голос
/ 21 апреля 2020

Другой вариант может быть:

dummy %>%
 group_by(category) %>%
 mutate(packet = ceiling(1:n()/packet_size))

     data category packet
    <dbl> <fct>     <dbl>
 1 0.288  A             1
 2 0.788  B             1
 3 0.409  A             1
 4 0.883  B             1
 5 0.940  B             2
 6 0.0456 A             2
 7 0.528  B             2
 8 0.892  B             3
 9 0.551  B             3
10 0.457  A             2
0 голосов
/ 21 апреля 2020

Мы также можем использовать gl

library(dplyr)
dummy %>%
   group_by(category) %>%
   mutate(packet = as.integer(gl(n(), packet_size, n())))

Или с data.table

library(data.table)
setDT(dummy)[, packet := as.integer(gl(n(), packet_size, n())), category]
0 голосов
/ 21 апреля 2020

Мы можем создать повторяющуюся последовательность с числом, повторяющимся packet_size раз для каждого category.

packet_size <- 2
library(dplyr)

dummy %>%
  group_by(category) %>%
  mutate(packet = rep(seq_len(n()), each = packet_size, length.out = n()))


#    data category packet
#    <dbl> <fct>     <int>
# 1 0.288  A             1
# 2 0.788  B             1
# 3 0.409  A             1
# 4 0.883  B             1
# 5 0.940  B             2
# 6 0.0456 A             2
# 7 0.528  B             2
# 8 0.892  B             3
# 9 0.551  B             3
#10 0.457  A             2
#...
#...

Решение data.table может быть полезным, так как у вас много строк.

library(data.table)
setDT(dummy)[, packet := rep(seq_len(.N), each = packet_size, length.out = .N), 
               category]

Вы также можете реализовать тот же лог c в базе R:

dummy$packet <- with(dummy, ave(data, category, FUN = function(x)
               rep(seq_along(x), each = packet_size, length.out = length(x))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...