2016-01-03 4 views
2
  • Текст, который я использую, приведен ниже.

До сих пор я импортировал текст:Как разбить скрипт воспроизведения с помощью формы ** Динамик: диалог **, чтобы получить диалог любого персонажа в один текстовый блок?

tempest.v <- scan("data/plainText/tempest.txt", what="character", sep="\n") 

Указано, где все позиции колонок начинаются:

speaker.positions.v <- grep('^[^\\s]\\w+:', tempest.v) 

Добавлен маркер в конце текста:

tempest.v <- c(tempest.v, "END:") 

Вот часть, где у меня возникают трудности (предположим ING, что я уже сделал это полезно):

for(i in 1:length(speaker.positions.v)){ 
    if(i != length(speaker.positions.v)){ 
     speaker.name <- debate.v[speaker.positions.v[i]] 
     speaker.name <- strsplit(speaker.name, ":") 
     speaker.name <- unlist(speaker.name) 
     start <- speaker.positions.v[i]+1 
     end <- speaker.positions.v[i+1]-1 
     speaker.lines.v <- debate.v[start:end] 
    } 
} 

Теперь у меня есть переменная speaker.name, что имеет, на левой стороне раскола, имя персонажа, который говорит. Правая часть раскола - это диалог только через первый разрыв строки.

Я установил начало из диалога блока в позиции [I] + 1 и конец в [I + 1] -1 (то есть, на одну позицию назад от начала имени последующий говорящего) ,

Теперь у меня есть переменная, speaker.lines.v со всеми линиями диалога для этого динамика для этой речи.

Как я могу собрать все диалог Прорандо, а затем Миранды (тогда любого другого персонажа) в единый (векторный кадр??) Для анализа?

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

С Новым годом!

--- * TEXT ---

* Miranda: Если вашим искусством, мой самый дорогой отец, у вас есть Помещенный дикие воды в этом реве, смягчать их. Небо, похоже, наполнило бы вонючую подачу, Но что море, установленное на щеке утки, Вычеркивает огонь. О, я пострадал С теми, что я видел, страдает - храброе судно,

У кого, без сомнения, какое-то благородное существо в ней, Dash'd все на куски. О, крик пробил Против моего сердца. Бедные души, они погибли. Если бы я был каким-то богом власти, я бы Погрузил море в землю или ere Он должен хороший корабль так проглотил и Чрезвычайные души внутри нее.

Просперо: Соберите: Нет больше удивления: расскажите своему жалобному сердцу Нет никакого вреда.

Миранда: О, горе день!

Просперо: никакого вреда. Я ничего не сделал, но в заботе о тебе, тебя, мой дорогой, ты, моя дочь, Art невежественны о том, что ты, ничто не зная Of откуда я, ни того, что я более лучше чем Просперо , хозяин полной бедной клетки, И твой не больший отец.

Миранда: Больше знать Никогда не вмешивался в мои мысли.

Просперо: «Время» Я должен сообщить вам дальше. Оденьте руку, И вытащить из меня мою магическую одежду. Итак:

[Ложится свою мантию]

Ли там, мое искусство. Протрите глаза ваши; есть приятный. ужасного зрелище остова, который touch'd Самой добродетель сострадания к тебе, я с таким положением в шахтных техниках Так что смело приказало нет soul- Нет, не так много погибели как волосы Бетид любому существу в сосуде Который ты слышал, крик, который ты видел, утонул. Сядьте; Ибо ты теперь должен знать дальше.

--- КОНЕЦ ТЕКСТА ---

+2

Я предполагаю, что текст Tempest доступен бесплатно (Gutenberg?). Не могли бы вы поделиться ссылкой на данные. – MichaelChirico

+0

также, вы будете счастливы узнать, что 'strsplit' работает на векторах, не нужно контура. – MichaelChirico

+3

@MichaelChirico Текст бухты Гутенберга доступен в 'learningr' pacakge. 'system.file (" extdata "," Shakespeare.s.The.Tempest..from.Project.Gutenberg.pg2235.txt ", package =" learningr ")' –

ответ

2

Я первый спас текст вы положили здесь test.txt. Потом прочитал:

tempest <- scan("~/Desktop/test.txt", what = "character", sep = "\n") 

Затем вытащил только произносимые линии, как вы:

speakers <- tempest[grepl("^[^\\s]\\w+:", tempest)] 

Тогда мы отделились имя говорящего:

speaker_split <- strsplit(speakers, split = ":") 

И получить имена:

speaker_names <- sapply(speaker_split, "[", 1L) 

И что они сказали (обрушиваются петь, потому что их линии, возможно, были и другие колонов, которые мы потеряли):

speaker_parts <- sapply(speaker_split, function(x) paste(x[-1L], collapse = ":")) 

Отсюда нам нужно просто показатели, которые сказали, что и мы можем делать то, что мы хотим:

prosp <- which(speaker_names == "Prospero") 
miran <- which(speaker_names == "Miranda") 

И играть в свой сердца.

Кто сказал, что больше всего слов?

> sum(unlist(strsplit(speaker_parts[prosp], split = "")) == " ") 
[1] 82 
> sum(unlist(strsplit(speaker_parts[miran], split = "")) == " ") 
[1] 67 

Просперо.

Какова частота писем, используемых Мирандой?

> table(tolower(unlist(strsplit(gsub("[^A-Za-z]", "", speaker_parts[miran]), 
         split = "")))) 

a b c d e f g h i k l m n o p r s t u v w y 
17 3 2 11 34 7 3 21 16 5 7 7 9 17 3 14 18 30 11 5 10 8 
+0

Майкл, спасибо за это элегантное решение. Работа заставила меня слишком заняться, чтобы выкопать - но сейчас это было предварительное испытание, и я думаю, что это будет сделано! Я хочу пройти код, чтобы убедиться, что я вижу все, что здесь происходит. - Philippe – user30938

+0

Оказалось, код, который вы представили, поскольку я думал, что это может из-за моего оригинального выражения grep, только поднимает первый абзац (до первого \ n) речи с несколькими параграфами. Я увижу, могу ли я изменить функцию для захвата всего текста. – user30938

2

Мы будем использовать rebus пакет для создания регулярных выражений, stringi, чтобы соответствовать этим регулярным выражениям, и data.table для хранения данных.

library(rebus) 
library(stringi) 
library(data.table) 

Первая отделка начальные и конечные пробелы из линий

tempest.v <- stri_trim(tempest.v) 

избавиться от пустых строк

tempest.v <- tempest.v[nzchar(tempest.v)] 

Выкрутить ремарках

stage_dir_rx <- exactly(
    OPEN_BRACKET %R% 
    one_or_more(printable()) %R% 
    "]" 
) 
is_stage_dir_line <- stri_detect_regex(tempest.v, stage_dir_rx) 
tempest.v <- tempest.v[!is_stage_dir_line] 

Совпадение строки, содержащие «характер : dialo GUE».

character_dialogue_rx <- START %R% 
    optional(capture(one_or_more(alpha()) %R% lookahead(":"))) %R% 
    optional(":") %R% 
    zero_or_more(space()) %R% 
    capture(one_or_more(printable())) 
matches <- stri_match_first_regex(tempest.v, character_dialogue_rx) 

Храните спички в data.table (нам это нужно для roll функциональности). Столбец с номером номера строки также необходим в любой момент.

tempest_data <- data.table(
    line_number = seq_len(nrow(matches)), 
    character = matches[, 2], 
    dialogue = matches[, 3] 
) 

восполнения недостающих значений, с использованием метода, описанного в this answer.

setkey(tempest_data, line_number) 
tempest_data[, character := tempest_data[!is.na(character)][tempest_data, character, roll = TRUE]] 

Данные в настоящее время сохраняются в виде строки: каждая строка содержит одну строку диалога.

line_number character     dialogue 
1:   1 Miranda If by your art, my de.... 
2:   2 Miranda Who had, no doubt, so.... 
3:   3 Prospero Be collected: No more.... 
4:   4 Miranda   O, woe the day! 
5:   5 Prospero No harm. I have done .... 
6:   6 Miranda More to know Did neve.... 
7:   7 Prospero 'Tis time I should in.... 
8:   8 Prospero Lie there, my art. Wi.... 

Чтобы получить весь диалог для заданного символа как отдельной строки, суммируйте с помощью аргумента by.

tempest_data[, .(all_dialogue = paste(dialogue, collapse = "\n")), by = "character"] 
2

Меня интересовал этот вопрос, потому что я разрабатываю серию инструментов для этих задач. Вот как решить эту проблему с помощью этих инструментов.

if (!require("pacman")) install.packages("pacman") 
pacman::p_load_gh("trinker/textshape", "trinker/qdapRegex") 
pacman::p_load(dplyr) 

pat <- '^[^\\s]\\w+:' 

"tempest.txt" %>%                        
    readLines() %>%                 
    {.[!grepl("^(---)|(^\\s*$)", .)]} %>% 
    split_match(pat, regex=TRUE, include=TRUE) %>% 
    textshape::combine() %>% 
    {setNames(., sapply(., function(x) unlist(ex_default(x, pattern = pat))))} %>% 
    bind_list("person") %>% 
    mutate(content = gsub(pat, "", content)) %>% 
    `[` %>% 
    textshape::combine() 

результат

 person          content 
1 Miranda: If by your art, my dearest father, you ... 
2 Prospero: Be collected No more amazement tell you .. 

Чтобы избежать объединения (В @RichieCotton отображается на начальном этапе) оставить от последнего textshape::combine() в цепочке.