Извлечь часть строки из одного столбца, вставить в новый столбец - PullRequest
0 голосов
/ 11 июня 2019

Отказ от ответственности: Совершенно неопытен с R, поэтому, пожалуйста, потерпите меня! ...

Контекст: у меня есть ряд файлов .csv в каталоге.Эти файлы содержат 7 столбцов и около 100 строк.Я скомпилировал несколько сценариев, которые будут читать во всех файлах, зацикливаясь на каждом из них, добавляя несколько новых столбцов на основе различных факторов (например, если конкретный столбец ссылается на «набор блоков», то он создает новый столбец с именем «box_set»)."с" да "или" нет "для каждой строки) и запишите поверх исходных файлов.Единственное, что я не могу понять (и да, я гуглил по максимуму и по минимуму), это как разделить один из столбцов на два, основываясь на определенной строке.Строка всегда начинается с «: Series», но может заканчиваться разными номерами или диапазонами чисел.Например, «Полдарк: серия 4», «Мушкетеры: серия 1-3».

Я хочу иметь возможность разбить этот столбец (в настоящее время называется Programme_Title) на два столбца (один называется Programme_Title, а другой - Series_Details).Programme_Title будет просто содержать все до ":", в то время как Series_Details будет содержать все, начиная с "S".

Чтобы еще больше усложнить ситуацию, столбец Programme_Title содержит ряд различных строк, не все из которых следуют примерамвыше.Некоторые не содержат «: Series», некоторые будут включать «:», но не будут сопровождаться «Series».

Поскольку я ужасно объясняю эти вещи, вот пример того, как это выглядит в настоящее время:

Programme_Title               
Hidden
Train Surfing Wars: A Matter of Life and Death
Bollywood: The World's Biggest Film Industry
Cuckoo: Series 4
Mark Gatiss on John Minton: The Lost Man of British Art
Love and Drugs on the Street
Asian Provocateur: Series 1-2
Poldark: Series 4
The Musketeers: Series 1-3
War and Peace

А вот как я хочу, чтобы это выглядело:

Programme_Title                                          Series_Details
Hidden
Train Surfing Wars: A Matter of Life and Death
Bollywood: The World's Biggest Film Industry
Cuckoo                                                   Series 4
Mark Gatiss on John Minton: The Lost Man of British Art
Love and Drugs on the Street
Asian Provocateur                                        Series 1-2
Poldark                                                  Series 4
The Musketeers                                           Series 1-3
War and Peace

Как я уже сказал, я новичок, так что представьте, что вы разговариваете с 5-летним.Если вам нужна дополнительная информация, чтобы ответить на этот вопрос, пожалуйста, дайте мне знать.

Вот код, который я использую, чтобы сделать все остальное (я уверен, что это немного грязно, но я собрал его вместе сразные источники, и это работает!)

### Read in files ###
filenames = dir(pattern="*.csv")

### Loop through all files, add various columns, then save ###

for (i in 1:length(filenames)) {
tmp <- read.csv(filenames[i], stringsAsFactors = FALSE)
### Add date part of filename to column labelled "date" ###
tmp$date <- str_sub(filenames[i], start = 13L, end = -5L)
### Create new column labelled "Series" ###
tmp$Series <- ifelse(grepl(": Series", tmp$Programme_Title), "yes", "no")
### Create "rank" for Programme_Category ###
tmp$rank <- sequence(rle(as.character(tmp$Programme_Category))$lengths)
### Create new column called "row" to assign numerical label to each group ###
DT = data.table(tmp)
tmp <- DT[, row := .GRP, by=.(Programme_Category)][]
### Identify box sets and create new column with "yes" / "no" ###
tmp$Box_Set <- ifelse(grepl("Box Set", tmp$Programme_Synopsis), "yes", "no")
### Remove the data.table which we no longer need ###
rm (DT)
### Write out the new file###
write.csv(tmp, filenames[[i]])
}

Ответы [ 2 ]

0 голосов
/ 11 июня 2019

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

Редактировать: я добавил контрольный пример, который не включал: или серию.Он просто выдаст NA для деталей серии.

## load library: main ones using are stringr, dplyr, tidry, and tibble from the tidyverse, but I would recommend just installing the tidyverse
library(tidyverse)

## example of your data, hard to know all the unique types of data, but this will get you in the right direction
data <- tibble(title = c("X:Series 1-6",
                         "Y: Series 1-2",
                         "Z : Series 1-10",
                         "The Z and Z: 1-3",
                         "XX Series 1-3",
                         "AA AA"))

## Example of the data we want to format, see the different cases covered
print(data)

  title           
  <chr>           
1 X:Series 1-6    
2 Y: Series 1-2   
3 Z : Series 1-10 
4 The Z and Z: 1-3
5 XX Series 1-3
6 AA AA   

## These %>% are called pipes, and used to feed data through a pipeline, very handy and useful.
data_formatted <- data %>%

  ## Need to fix cases where you have Series but no : or vice versa, this keep everything the same.
  ## Sounds like you will always have either :, series, or :Series If this is different you can easily
  ## change/update this to capture other cases
  mutate(title = case_when(
    str_detect(title,'Series') & !(str_detect(title,':')) ~ str_replace(title,'Series',':Series'),
    !(str_detect(title,'Series')) & (str_detect(title,':')) ~ str_replace(title,':',':Series'),
    TRUE ~ title)) %>% 

  ## first separate the columns based on :
  separate(col = title,into = c("Programme_Title","Series_Details"), sep  = ':') %>% 

  ##This just removes all white space at the ends to clean it up
  mutate(Programme_Title = str_trim(Programme_Title),
         Series_Details = str_trim(Series_Details))

## Output of the data to see how it was formatted
print(data_formatted)

  Programme_Title Series_Details
  <chr>           <chr>         
1 X               Series 1-6    
2 Y               Series 1-2    
3 Z               Series 1-10   
4 The Z and Z     Series 1-3    
5 XX              Series 1-3
6 AA AA           NA  
0 голосов
/ 11 июня 2019

У меня нет вашей точной структуры данных, но я создал для вас пример, который должен работать:

library(tidyr)
movieName <- c("This is a test", "This is another test: Series 1-5", "This is yet another test")
df <- data.frame(movieName)
df
                         movieName
1                   This is a test
2 This is another test: Series 1-5
3         This is yet another test
df <- df %>% separate(movieName, c("Title", "Series"), sep= ": Series")

for (row in 1:nrow(df)) {
  df$Series[row] <- ifelse(is.na(df$Series[row]), "", paste("Series", df$Series[row], sep = ""))
}
df
                     Title     Series
1           This is a test           
2     This is another test Series 1-5
3 This is yet another test       
...