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

#r

#r

Вопрос:

У меня есть следующая таблица, которая содержит факторную переменную «категория» с двумя уровнями DH1 и DH2. У меня также есть значения интервалов для факторной переменной ‘from’ и ‘to’.

 category = c('DH1','DH1','DH1','DH1','DH2','DH2')
from = c(356,366,367,368,401,402)
to = c(366,367,368,369,402,403)

df <- data.frame(category,from, to)

  category from  to
1      DH1  365 366
2      DH1  366 367
3      DH1  367 368
4      DH1  368 369
5      DH2  401 402
6      DH2  402 403
  

Мне нужно создать два новых столбца, которые могут выглядеть следующим образом: как только DH1 изменяется на DH2, from1 начинается с 0 и to1 = to-from

   category from  to from1 to1
1      DH1  365 366     0   1
2      DH1  366 367     1   2
3      DH1  367 368     2   3
4      DH1  368 369     3   4
5      DH2  401 402     0   1
6      DH2  402 403     1   2
  

Я понимаю, что мне нужно иметь цикл for и перебирать ‘category’, затем иметь оператор if category[4] != category[5] и на основе этого вычислять новые столбцы. Но есть ли более простой способ сделать это?

Комментарии:

1. Как только DH1 изменяется на DH2, значение from1 начинается с 0 и to1 = to-from.

2. … и аналогично вопросу @Ronak, для 1-й строки, как to1 1? to - from является 366 - 356 = 10

3. @MauritsEvers Я исправил эту ошибку, приношу свои извинения за это! Это кумулятивное добавление, поскольку вторая строка to1 равна второй строке from1 1.

Ответ №1:

Существует простой способ, использующий library(dplyr) :

 df %>% arrange(category, from) 
  %>% group_by(category) 
  %>% mutate(from1 = row_number()-1, to1 = row_number())
  

Он сортирует данные по category и from и группирует по category переменной, чтобы убедиться, что from1 и to1 могут быть основаны на номерах строк для каждой категории, используя mutate функцию, которая используется для создания новых переменных.

Комментарии:

1. Это будет работать, но только в том случае, если интервалы всегда равны 1, но иногда они могут быть 1,5 или 2. от = 402,5 до = 404.

2. марианесс, ты никогда не показывала это в качестве примера. Все ваши входные данные показывали подсчет от 0 до n-1 или от 1 до n. Ответ @ Arnaud полностью правильный и поясняющий. Это хороший ответ. Пожалуйста, примите ответ и создайте новый вопрос с примерами, охватывающими все ваши случаи.

Ответ №2:

Возможно, вы ищете

 library(dplyr)

df %>%
  group_by(category) %>%
  mutate(from1 = row_number() - 1, 
          to1 = cumsum(to - from))


#  category  from    to from1   to1
#  <fct>    <dbl> <dbl> <dbl> <dbl>
#1 DH1        365   366     0     1
#2 DH1        366   367     1     2
#3 DH1        367   368     2     3
#4 DH1        368   369     3     4
#5 DH2        401   402     0     1
#6 DH2        402   403     1     2
  

Для каждого category это присваивает row_number() - 1 значение from1 и вычисляет совокупную сумму to - from значений. Если category не упорядочен и DH1 может возникнуть снова как другая группа, нам может понадобиться group_by data.table::rleid(category) .

Ответ №3:

Если вы нумеруете 1 ..n внутри каждой категории, вы можете использовать пакет «dplyr»:

 library(dplyr)
df %>% group_by(category) %>% mutate(to1=1:n(), from1=to1-1)
  

Если вы пытаетесь сравнить значение в строке i со строкой i 1, вы можете использовать функцию lag , также из «dplyr» (встроенная lag функция работает только с временными рядами):

 dplyr::lag(df$category)
[1] <NA> DH1  DH1  DH1  DH1  DH2 
Levels: DH1 DH2
  

(как только вы загрузите пакет «dplyr», он заменит встроенную lag функцию, и вам не нужно вызывать ее, как я написал в примере — это было просто для того, чтобы подчеркнуть, о какой функции я говорю)