Как добавить столбец с прогрессивным номером на основе условия - PullRequest
1 голос
/ 10 мая 2019

Я пытаюсь добавить столбец в мой существующий набор данных.Набор данных имеет три столбца:

  • Student (это столбец с идентификатором участника),
  • Week (номер недели в году, в течение которогоданные были собраны), и
  • Day (номер дня недели, в течение которого были собраны данные).

Теперь появился новый столбец Obs, которым я являюсьпопытка создать будет содержать прогрессивное число (от 1 до n), относящееся к неделе, в течение которой тестировался каждый студент.

Я пытался использовать group_by в сочетании с rep, но это не похожечтобы получить желаемый результат:

Week <- c(1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4)
Day <- c(1, 2, 3, 2, 3, 5, 1, 3, 2, 3, 4, 5)
Student <- c("A", "A", "A", "B", "B", "B", "B", "B", "C", "C", "C", "C")
fake.db <- data.frame(Student, Week, Day)

library(dplyr)
fake.db %>%
  group_by(Student) %>% 
  mutate(Obs = rep(1:length(Student), each = Week))
#   Student  Week   Day   Obs
#   <fct>   <dbl> <dbl> <int>
# 1 A           1     1     1
# 2 A           1     2     2
# 3 A           1     3     3
# 4 B           2     2     1
# 5 B           2     3     2
# 6 B           2     5     3
# 7 B           3     1     4
# 8 B           3     3     5
# 9 C           4     2     1
#10 C           4     3     2
#11 C           4     4     3
#12 C           4     5     4

То, что я хотел бы получить, отличается.За первую неделю сбора данных следует сообщать 1, а для студентов, для которых данные были собраны в течение второй недели, следует указывать 2 и т. Д.:

#   Student Week Day Obs
#1        A    1   1   1
#2        A    1   2   1
#3        A    1   3   1
#4        B    2   2   1
#5        B    2   3   1
#6        B    2   5   1
#7        B    3   1   2
#8        B    3   3   2
#9        C    4   2   1
#10       C    4   3   1
#11       C    4   4   1
#12       C    4   5   1

Ответы [ 4 ]

4 голосов
/ 10 мая 2019

Одна dplyr возможность может быть:

fake.db %>%
 group_by(Student) %>%
 mutate(Obs = cumsum(!duplicated(Week)))

  Student  Week   Day   Obs
   <fct>   <dbl> <dbl> <int>
 1 A           1     1     1
 2 A           1     2     1
 3 A           1     3     1
 4 B           2     2     1
 5 B           2     3     1
 6 B           2     5     1
 7 B           3     1     2
 8 B           3     3     2
 9 C           4     2     1
10 C           4     3     1
11 C           4     4     1
12 C           4     5     1

Группируется по столбцу «Студент» и рассчитывает совокупную сумму неповторяющихся значений «Неделя».

Или:

fake.db %>%
 group_by(Student) %>%
 mutate(Obs = with(rle(Week), rep(seq_along(lengths), lengths)))

Группируется по столбцу «Студент» и создает идентификатор группы типов длины строки вокруг столбца «Неделя».

Или:

fake.db %>%
 group_by(Student) %>%
 mutate(Obs = dense_rank(Week))

Группируется по столбцу «Студент» и ранжирует значения в столбце «Неделя».

2 голосов
/ 11 мая 2019

Краткий метод с by

unlist(by(fake.db, fake.db[, 1], function(x) as.numeric(factor(x[, 2]))))
# A1 A2 A3 B1 B2 B3 B4 B5 C1 C2 C3 C4 
#  1  1  1  1  1  1  2  2  1  1  1  1

Данные

fake.db <- structure(list(Student = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 
2L, 2L, 3L, 3L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), 
    Week = c(1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4), Day = c(1, 
    2, 3, 2, 3, 5, 1, 3, 2, 3, 4, 5)), class = "data.frame", row.names = c(NA, 
-12L))
2 голосов
/ 10 мая 2019

Я понимаю, что проблема в том, что вы хотите сосчитать недели с первой тестовой недели для каждого учащегося.Т.е. неделя 2 - первая неделя тестирования ученика B, поэтому она получает Obs = 1.Это означает, что вы можете выполнить групповое преобразование:

library(dplyr)
fake.db <- structure(list(Student = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), Week = c(1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4), Day = c(1, 2, 3, 2, 3, 5, 1, 3, 2, 3, 4, 5)), class = "data.frame", row.names = c(NA, -12L))
fake.db %>%
  group_by(Student) %>%
  mutate(Obs = Week - min(Week) + 1)
#> # A tibble: 12 x 4
#> # Groups:   Student [3]
#>    Student  Week   Day   Obs
#>    <fct>   <dbl> <dbl> <dbl>
#>  1 A           1     1     1
#>  2 A           1     2     1
#>  3 A           1     3     1
#>  4 B           2     2     1
#>  5 B           2     3     1
#>  6 B           2     5     1
#>  7 B           3     1     2
#>  8 B           3     3     2
#>  9 C           4     2     1
#> 10 C           4     3     1
#> 11 C           4     4     1
#> 12 C           4     5     1

Создано в 2019-05-10 пакетом Представить (v0.2.1)

1 голос
/ 10 мая 2019

Вы можете увидеть, есть ли ненулевая разница

fake.db %>%
  group_by(Student) %>% 
  arrange(Week) %>%
  mutate(Obs = cumsum(c(1, diff(Week)!=0)))

или если их значения не являются числовыми, вы можете сравнить их со значением лага

fake.db %>%
  group_by(Student) %>% 
  arrange(Week) %>%
  mutate(Obs = cumsum(Week != lag(Week, default=first(Week))) + 1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...