Добавьте столбец, основанный на двух разных столбцах, каждый из которых имеет несколько разных имен

#r #dplyr #group-by #assign

Вопрос:

У меня есть набор данных, который включает в себя номер этапа и номер машины — небольшая часть воспроизведена ниже. Однако на самом деле полный набор данных включает 38 этапов и имеет длину более 1 миллиона строк.

 stage <- c("Stg1",  "Stg1","Stg1","Stg1","Stg1","Stg1","Stg1","Stg1","Stg1","Stg1","Stg1","Stg1",   "Stg2", "Stg2", "Stg2","Stg2","Stg2","Stg2","Stg2","Stg2","Stg2","Stg2","Stg10","Stg10","Stg10")
machine <- c("132H", "132H","132H", "132H", "132H", "212H", "212H", "212H", "212H", "212H", "217H", "217H", "132H", "132H", "212H", "212H", "212H", "212H", "212H", "217H", "217H", "217H", "132H", "132H", "132H")

df <- data.frame(stage,machine)

head(df)
  stage machine
1  Stg1    132H
2  Stg1    132H
3  Stg1    132H
4  Stg1    132H
5  Stg1    132H
6  Stg1    212H
 

Моя цель-создать новый столбец, который будет последовательно присваивать номера сгруппированным этапам и машинам. В конечном счете, код, который будет выдавать результат, подобный этому:

 Stage   Machine JobStage
Stg1    132H    1
Stg1    132H    1
Stg1    132H    1
Stg1    132H    1
Stg1    132H    1
Stg1    212H    2
Stg1    212H    2
Stg1    212H    2
Stg1    212H    2
Stg1    212H    2
Stg1    217H    3
Stg1    217H    3
Stg2    132H    4
Stg2    132H    4
Stg2    212H    5
Stg2    212H    5
Stg2    212H    5
Stg2    212H    5
Stg2    212H    5
Stg2    217H    6
Stg2    217H    6
Stg2    217H    6
Stg10   132H    7
Stg10   132H    7
Stg10   132H    7
 

Я знаю, что вы можете сделать что-то подобное для каждого этапа и каждой машины, но это отнимает много времени, особенно для большого набора данных:

 df$JobStage[df$stage == "Stg1" amp; df$machine == "132H"] <- 1
df$JobStage[df$stage == "Stg1" amp; df$machine == "212H"] <- 2
...
 

Я пытался использовать dplyr с group_by() и mutate(), но я не уверен, как правильно захватить различные этапы и машины и присвоить им номер. Я знаю, что функция unique() не работает для значений символов, но, возможно, код будет примерно таким:

 df %>% group_by(stage, machine) %>% mutate(JobStage = unique(stage) amp; unique(machine))
 

Любая помощь была бы очень признательна. Спасибо.

Ответ №1:

Вот опция с unite и match , т. е. unite столбцы «этап», «машина», чтобы создать новый вставленный столбец и получить индекс по matching элементам со unique значениями

 library(dplyr)
library(tidyr)
df %>% 
   unite(JobStage, stage, machine, remove = FALSE) %>% 
   mutate(JobStage = match(JobStage, unique(JobStage)))
 

-выход

     JobStage stage machine
1         1  Stg1    132H
2         1  Stg1    132H
3         1  Stg1    132H
4         1  Stg1    132H
5         1  Stg1    132H
6         2  Stg1    212H
7         2  Stg1    212H
8         2  Stg1    212H
9         2  Stg1    212H
10        2  Stg1    212H
11        3  Stg1    217H
12        3  Stg1    217H
13        4  Stg2    132H
14        4  Stg2    132H
15        5  Stg2    212H
16        5  Stg2    212H
17        5  Stg2    212H
18        5  Stg2    212H
19        5  Stg2    212H
20        6  Stg2    217H
21        6  Stg2    217H
22        6  Stg2    217H
 

Ответ №2:

Один из вариантов:

 library(tidyverse)
df %>% 
  mutate(stag_mach = str_c(stage, machine),
         JobStage = as.integer(factor(stag_mach))) %>% 
  select(-stag_mach)
#    stage machine JobStage
# 1   Stg1    132H        1
# 2   Stg1    132H        1
# 3   Stg1    132H        1
# 4   Stg1    132H        1
# 5   Stg1    132H        1
# 6   Stg1    212H        2
# 7   Stg1    212H        2
# 8   Stg1    212H        2
# 9   Stg1    212H        2
# 10  Stg1    212H        2
# 11  Stg1    217H        3
# 12  Stg1    217H        3
# 13  Stg2    132H        4
# 14  Stg2    132H        4
# 15  Stg2    212H        5
# 16  Stg2    212H        5
# 17  Stg2    212H        5
# 18  Stg2    212H        5
# 19  Stg2    212H        5
# 20  Stg2    217H        6
# 21  Stg2    217H        6
# 22  Stg2    217H        6
 

РЕДАКТИРОВАТЬ: И если вы хотите сохранить порядок:

 df %>% 
  mutate(stag_mach = str_c(stage, machine),
         JobStage = as.integer(fct_inorder(stag_mach))) %>% 
  select(-stag_mach)
#    stage machine JobStage
# 1   Stg1    132H        1
# 2   Stg1    132H        1
# 3   Stg1    132H        1
# 4   Stg1    132H        1
# 5   Stg1    132H        1
# 6   Stg1    212H        2
# 7   Stg1    212H        2
# 8   Stg1    212H        2
# 9   Stg1    212H        2
# 10  Stg1    212H        2
# 11  Stg1    217H        3
# 12  Stg1    217H        3
# 13  Stg2    132H        4
# 14  Stg2    132H        4
# 15  Stg2    212H        5
# 16  Stg2    212H        5
# 17  Stg2    212H        5
# 18  Stg2    212H        5
# 19  Stg2    212H        5
# 20  Stg2    217H        6
# 21  Stg2    217H        6
# 22  Stg2    217H        6
# 23 Stg10    132H        7
# 24 Stg10    132H        7
# 25 Stg10    132H        7
 

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

1. Это работает для этого меньшего примера, но в моем большем наборе данных он присваивает 7 первому этапу работы (т. Е. этап = stg1 и машина = 132 Ч). Я посмотрел, и это присваивает 1 этапу работы, когда этап = stg10 и машина = 132 часа. Это проблема для двухзначных этапов (например, Stg10, Stg11 и т. Д.). Должен ли я отредактировать приведенный выше пример кода, чтобы включить Stg10 и так далее?

2. Я отредактировал пример в исходном посте, чтобы лучше решить эту проблему. Спасибо

3. смотрите обновление, вам просто нужно упорядочить факторную переменную так, как вы видите ее в наборе данных.