2017-02-23 1 views
1

J'utilise tidytext (et tidyverse) pour analyser certaines données de texte (comme dans Tidy Text Mining with R).Etiquetage de section simple avec tidytext pour la saisie de texte en clair

Mon fichier texte d'entrée, myfile.txt, ressemble à ceci:

# Section 1 Name 
Lorem ipsum dolor 
sit amet ... (et cetera) 
# Section 2 Name 
<multiple lines here again> 

avec quelque 60 sections.

Je voudrais générer une colonne section_name avec les chaînes "Category 1 Name" ou "Category 2 Name" comme valeurs pour les lignes correspondantes. Par exemple, je

library(tidyverse) 
library(tidytext) 
library(stringr) 

fname <- "myfile.txt" 
all_text <- readLines(fname) 
all_lines <- tibble(text = all_text) 
tidiedtext <- all_lines %>% 
    mutate(linenumber = row_number(), 
     section_id = cumsum(str_detect(text, regex("^#", ignore_case = TRUE)))) %>% 
    filter(!str_detect(text, regex("^#"))) %>% 
    ungroup() 

qui ajoute une colonne tidiedtext pour le numéro de section correspondante pour chaque ligne.

Est-il possible d'ajouter une seule ligne à l'appel à mutate() pour ajouter une telle colonne? Ou y a-t-il une autre approche que je devrais utiliser?

Répondre

0

Voici une approche utilisant grepl pour simplifier avec if_else et tidyr::fill, mais il n'y a rien de mal avec l'approche originale; C'est assez similaire à celui utilisé dans le livre TidyTex. Notez également que le filtrage après l'ajout de numéros de ligne en rendra certains inexistants. Si c'est important, ajoutez les numéros de ligne après filter.

library(tidyverse) 

text <- '# Section 1 Name 
Lorem ipsum dolor 
sit amet ... (et cetera) 
# Section 2 Name 
<multiple lines here again>' 

all_lines <- data_frame(text = read_lines(text)) 

tidied <- all_lines %>% 
    mutate(line = row_number(), 
      section = if_else(grepl('^#', text), text, NA_character_)) %>% 
    fill(section) %>% 
    filter(!grepl('^#', text)) 

tidied 
#> # A tibble: 3 × 3 
#>       text line   section 
#>       <chr> <int>   <chr> 
#> 1   Lorem ipsum dolor  2 # Section 1 Name 
#> 2 sit amet ... (et cetera)  3 # Section 1 Name 
#> 3 <multiple lines here again>  5 # Section 2 Name 

Ou si vous voulez juste formater les chiffres que vous avez déjà, il suffit d'ajouter section_name = paste('Category', section_id, 'Name') à votre appel mutate.

+0

Merci! C'est à peu près ce que je cherchais. – weinerjm

1

Je ne veux pas vous faire réécrire votre script en entier, mais je trouve intéressant et pensé à la question d'ajouter une base R provisoire:

parse_data <- function(file_name) { 
    all_rows <- readLines(file_name) 
    indices <- which(grepl('#', all_rows)) 
    splitter <- rep(indices, diff(c(indices, length(all_rows)+1))) 
    lst <- split(all_rows, splitter) 
    lst <- lapply(lst, function(x) { 
    data.frame(section=x[1], value=x[-1], stringsAsFactors = F) 
    }) 
    line_nums = seq_along(all_rows)[-indices] 
    df <- do.call(rbind.data.frame, lst) 
    cbind.data.frame(df, linenumber = line_nums) 
} 

test avec un fichier nommé ipsum_data.txt:

parse_data('ipsum_data.txt') 

rendements:

text      section   linenumber 
Lorem ipsum dolor   # Section 1 Name 2   
sit amet ... (et cetera) # Section 1 Name 3   
<multiple lines here again> # Section 2 Name 5 

Le fichier ipsum_data.txt contient:

# Section 1 Name 
Lorem ipsum dolor 
sit amet ... (et cetera) 
# Section 2 Name 
<multiple lines here again> 

J'espère que cela s'avère utile.

+0

Merci pour la réponse. C'est très utile. Ce n'est pas un gros problème pour moi de réécrire le script, mais je pense que l'autre solution est plus ce que je cherchais en termes de concision. – weinerjm