Добавление строк в набор данных в соответствии с переменной - PullRequest
0 голосов
/ 04 февраля 2020

У меня есть набор данных, который содержит значение «DoW» (дни недели), отформатированное так: 1__45_7 (всегда 7 символов). И я хочу продублировать строки моего набора данных для каждого номера DoW. Например, для этого набора данных:

ColA; ColB; DoW;
PAR; БКК; 1_3_5 __
NYC; LON; 1_____7

Если у меня есть «1_3_5__» в переменной «DoW», так как в этой переменной 3 числа, я должен дублировать ее 2 раза, чтобы эта строка была 3 раза. В каждом дублировании строки мне нужно одно из чисел начального значения DoW. Таким образом, вывод должен быть:

ColA; ColB; DoW;
PAR; БКК; 1;
PAR; БКК; 3;
PAR; БКК; 5;
NYC; LON; 1;
NYC; LON; 7;

Я пробовал много решений, но не смог понять это. У вас есть чистый способ сделать это с R?

Спасибо!

Ответы [ 3 ]

0 голосов
/ 04 февраля 2020

Вот решение tidyverse:

library(tidyverse)

df %>%
  separate(DoW, into = c(paste0("Day_", 1:7)), sep = 1:6) %>%
  pivot_longer(cols = starts_with("Day"), names_to = c(".value", "DoW"), names_sep = "_") %>%
  filter(Day != "_") %>%
  select(-Day)

Обратите внимание, что DoW отражает позицию в строке (от 1 до 7), которая в данном случае совпадает с отдельными числами в строке. Если вы хотите sh сохранить оба (фактическое число и местоположение в строке), то вы можете удалить select(-Day), поскольку Day будет иметь фактическое число.

Выход

# A tibble: 5 x 3
  ColA  ColB  DoW  
  <fct> <fct> <chr>
1 PAR   BKK   1    
2 PAR   BKK   3    
3 PAR   BKK   5    
4 NYC   LON   1    
5 NYC   LON   7 

Данные

df <- data.frame(
  ColA = c("PAR", "NYC"),
  ColB = c("BKK", "LON"),
  DoW = c("1_3_5__", "1_____7")
)
0 голосов
/ 04 февраля 2020

Вот data.table подход к вашему вопросу

library(data.table)

#create sample data
dt <- fread("ColA; ColB; DoW
PAR; BKK; 1_3_5__
NYC; LON; 1_____7 ", sep  =";")

#remove all underscores from DoW, split by character and melt to long format
ans <- melt( 
  copy(dt)[, paste0( "DoW", 1:length(tstrsplit(gsub("_","",dt$DoW), ""))) := 
       tstrsplit(gsub("_","",dt$DoW), "") ],
  id.vars = c("ColA", "ColB"), 
  measure.vars = patterns("^DoW[0-9]"), 
  value.name = "DoW", 
  na.rm = TRUE )
#remove unneeded variable
ans[, variable := NULL][]


#    ColA ColB DoW
# 1:  PAR  BKK   1
# 2:  NYC  LON   1
# 3:  PAR  BKK   3
# 4:  NYC  LON   7
# 5:  PAR  BKK   5

объяснение

строка

copy(dt)[, paste0( "DoW", 1:length(tstrsplit(gsub("_","",dt$DoW), ""))) := 
     tstrsplit(gsub("_","",dt$DoW), "") ]

приводит к временной data.table со всеми расщепленными DoW-номерами, как это

#    ColA ColB     DoW DoW1 DoW2 DoW3
# 1:  PAR  BKK 1_3_5__    1    3    5
# 2:  NYC  LON 1_____7    1    7 <NA>

, это можно «легко» растопить.

0 голосов
/ 04 февраля 2020

Спасибо за то, что пытаетесь быть яснее и пытаетесь добавить минимальный воспроизводимый пример! Это помогло мне понять ваш вопрос! Вероятно, есть много способов сделать то, что вы хотите, вот одно решение с использованием циклов:

Создайте пример данных, как в вашем вопросе:

df <- data.frame(ColA=c("PAR", "NYC", "EEE"),
                 ColB=c("BKK", "LON", "ZRH"),
                 DoW = c("1_3_5__", "1_____7", "__"),
                 stringsAsFactors = FALSE)

Создайте пустой data.frame для получить результаты

resulting_df <- data.frame(ColA = character(),
                           ColB = character(),
                           Number = numeric(),
                           stringsAsFactors = FALSE)

Теперь получите числа из столбца 'DoW', используя strsplit

numbers_list <- sapply(df$DoW, strsplit, "_")

Наконец, выполните итерации по каждой строке df и по каждой цифре в соответствующая запись в numbers_list (используя [[1]] для получения актуального содержимого!)

for (i in 1:nrow(df)) {
  for (number in numbers_list[i][[1]]) {
    if (!number %in% c("")) {
      new_line <- data.frame(ColA = df$ColA[i], ColB = df$ColB[i], Number = number, stringsAsFactors = FALSE)
      resulting_df <- rbind(resulting_df, new_line)
    }
  }
}

Объект resulting_df теперь должен иметь правильную форму.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...