Добавление строк для пропущенных этапов в процессе

#r #dataframe #analytics

#r #фрейм данных #аналитика

Вопрос:

Я хочу взять фрейм данных в R и увеличить его на основе того, что я вижу в двух столбцах, V1 и V2. Короче говоря, у меня есть этапы S1-S6, которые являются строками.

Для каждой строки, в которой на этапе есть пробел, мне нужно добавить строки. Глядя на фреймы данных ниже, если бы я увидел ‘S 3’ и ‘S 3’ в одной строке, мне не нужно было бы ничего делать. Аналогично, если бы я увидел ‘S 3’ и ‘S 4’ в одной строке, мне тоже ничего не нужно было бы делать.

Пример 1

Ввод:

 ----------------------------------
|Var1               | V1   | V2  |    
----------------------------------
|0060a00000fUbAnAAK |'S 2' |'S 5'|
----------------------------------
  

Вывод:

 ----------------------------------
|Var1               | V1   | V2  |    
----------------------------------
|0060a00000fUbAnAAK |'S 2' |'S 3'|
----------------------------------
|0060a00000fUbAnAAK |'S 3' |'S 4'|
----------------------------------
|0060a00000fUbAnAAK |'S 4' |'S 5'|
----------------------------------
  

Пример 2

Ввод:

 ----------------------------------
|Var1               | V1   | V2  |    
----------------------------------
|0060a00000fUbAnAAK |'S 5' |'S 3'|
----------------------------------
  

Вывод:

 ----------------------------------
|Var1               | V1   | V2  |    
----------------------------------
|0060a00000fUbAnAAK |'S 5' |'S 4'|
----------------------------------
|0060a00000fUbAnAAK |'S 4' |'S 3'|
----------------------------------
  

Ответ №1:

Идея использования tidyverse заключается в преобразовании в длинный формат, отделении чисел от S последовательности и завершении. Как только мы получим это, мы вставляем столбцы обратно вместе ( S и values ) и преобразуем обратно в широкий формат. Наконец, мы берем запаздывающую переменную V1 и удаляем NA s, т.е.

 library(tidyverse)

df %>% 
 gather(var, val, -1) %>% 
 separate(val, into = c('char', 'number'), sep = ' ') %>% 
 mutate(number = as.numeric(number)) %>% 
 complete(nesting(var, Var1, char), number = full_seq(min(number):max(number), 1)) %>%
 unite('V1_2', c('char', 'number'), sep = ' ') %>% 
 group_by(var) %>% 
 mutate(new = row_number()) %>% 
 spread(var, V1_2) %>% 
 mutate(V1 = lag(V1)) %>% 
 na.omit() %>% 
 select(-new)
  

что дает,

 # A tibble: 3 x 3
   Var1  V1    V2   
  <chr> <chr> <chr>
1 xxx   S 2   S 3  
2 xxx   S 3   S 4  
3 xxx   S 4   S 5 
  

Ответ №2:

обновленный ответ

Это обновление также учитывает уменьшение этапов

пример данных

 library(data.table)
DT <- fread("Var1               | V1   | V2
  0060a00000fUbAnAAK |S 2 |S 5
  0060a00000fUbAnAAK_ |S 5 |S 3")

#                   Var1  V1  V2
# 1:  0060a00000fUbAnAAK S 2 S 5
# 2: 0060a00000fUbAnAAK_ S 5 S 3
  

код

 #determine order of stages
DT[ as.numeric( gsub("[^0-9]", "", V2 ) ) < as.numeric( gsub("[^0-9]", "", V1 ) ), order := "desc" ]
DT[ is.na( order) , order := "asc" ]
#melt DT to long format
DT <- melt( DT, id.vars = c("Var1","order"), value.name = "stage")
#get stage as numeric and clean up unwanted columns
DT[, `:=`(stage = as.numeric( gsub("[^0-9]", "", stage)))]
#create new stages based on minimum and maximum stage per Var1-value
#use different methodes of ascending and descneding stages, then bind the rows together
rbind(
  DT[order == "asc", .( V1 = paste0( "S ", min(stage): (max(stage) - 1 ) ), 
                        V2 = paste0( "S ", (min(stage) 1):max(stage) ) ), by = .(Var1)],
  DT[order == "desc", .( V1 = paste0( "S ", max(stage): (min(stage)   1 ) ), 
                         V2 = paste0( "S ", (max(stage)-1):min(stage) ) ), by = .(Var1)]
)
  

вывод

 #                   Var1  V1  V2
# 1:  0060a00000fUbAnAAK S 2 S 3
# 2:  0060a00000fUbAnAAK S 3 S 4
# 3:  0060a00000fUbAnAAK S 4 S 5
# 4: 0060a00000fUbAnAAK_ S 5 S 4
# 5: 0060a00000fUbAnAAK_ S 4 S 3
  

предыдущий ответ

 `data.table` solution

**sample data**

    library(data.table)
    DT <- fread("Var1               | V1   | V2
      0060a00000fUbAnAAK |S 2 |S 5")

**code**

    #melt DT to long format
    DT <- melt( DT, id.vars = "Var1", value.name = "stage")
    #get stage as numeric and clean up unwanted columns
    DT[, `:=`(variable = NULL, stage = as.numeric( gsub("[^0-9]", "", stage)))]
    #create new stages based on minimum and maximum stage per Var1-value
    DT[, .( V1 = paste0( "S ", min(stage):(max(stage)-1) ),
            V2 = paste0( "S ", (min(stage) 1):max(stage) ) ), by = .(Var1)][]

**output**

    #                  Var1  V1  V2
    # 1: 0060a00000fUbAnAAK S 2 S 3
    # 2: 0060a00000fUbAnAAK S 3 S 4
    # 3: 0060a00000fUbAnAAK S 4 S 5
  

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

1. обновление alse обрабатывает уменьшающиеся этапы, как указано в example 2 вопросе