R语言如何按规则拆分文本章节生成对应命名data.frame
R按章节规则拆分文本数据框实现方案
需求说明
现有包含ID、text两列的data.frame对象:
text字段按章节划分,不同观测的章节设置不统一- 章节识别规则:章节起始位置带罗马数字编号(I、II……),章节标题为全大写文本,章节正文以
art或Art开头的条款起始 - 目标:按章节名(去除罗马数字编号,例如
DO CAPITAL SOCIAL)拆分为独立data.frame,每个对象保留原ID列和对应章节的文本内容。
示例原始数据
df <- structure(list(ID = c("56456", "1234564565921"), text = c("TÍTULO II OBJETIVOS Art. 2 A Cooperativa terá por objetivo a educação cooperativista e financeira dos seus associados, através da ajuda mútua, da economia sistemática e do uso adequado do crédito. Procurará, ainda, e por todos os meios, fomentar a expansão do Cooperativismo de economia e crédito mútuo. ¶ Único Em todos os aspectos de suas atividades, serão rigorosamente observados os princípios de neutralidade política e indiscriminação religiosa, racial e social. | TÍTULO III DAS ASSEMBLÉIAS GERAIS Art. 3 O número de associados será ilimitado, mas não poderá ser inferior a 20 (vinte). | Art. 4 Poderão associar-se à Cooperativa todos aqueles que, tendo livre disposição de pessoas e bens, concordem com o presente Estatuto, preencham as condições nele estabelecida e sejam empregados dahuiljl S/A, citada no Art. 1, letra C. TÍTULO IV DO CAPITAL SOCIAL Art. 21 – Texto grande aqui para parecer que tem coisa, deveria ter pego algo de outro lugar para dar esse exemplo", "IV DO CAPITAL SOCIAL Art. 21 – O Capital Social é ilimitado quanto ao máximo e variável, conforme o número de quotas-partes subscritas, não podendo, porém, o valor ser inferior à R$ 5.000,00 (cinco mil reais). Parágrafo 1º – O Capital Social é dividido em quotas-partes de R$ 1,00(um real) cada uma, integralizável em duas parcelas de 50% (cinqüenta por cento) cada, em moeda corrente nacional, a primeira no ato da subscrição e a segunda em até um ano após a primeira. Parágrafo 2º – O associado ao ingressar na cooperativa se obriga a subscrever, 300 (trezentas) quotas-partes. V DAS ASSEMBLÉIAS GERAIS Art. 22 – A Assembléia Geral dos associados é o órgão supremo da Cooperativa, e dentro dos limites da lei e deste estatuto, tomará toda e qualquer decisão de interesse da sociedade, e suas deliberações vinculam a todos, ainda que ausentes ou discordantes. Art. 23 – A Assembléia Geral será normalmente convocada e dirigida pelo Presidente da Cooperativa. Parágrafo 1º - Poderá, também, ser convocada pelo Conselho de Administração ou pelo Conselho Fiscal, se ocorrerem motivos graves ou urgentes, ou por 1/5 (um quinto) dos associados em pleno gozo de seus direitos sociais, após solicitação não atendida, comprovadamente, num prazo máximo de 5 (cinco) dias. " )), row.names = 1:2, class = "data.frame")
预期输出示例
DOCAPITALSOCIAL <- structure(list(ID = c("56456", "1234564565921"), text = c(" Art. 21 – Texto grande aqui para parecer que tem coisa, deveria ter pego algo de outro lugar para dar esse exemplo", "Art. 21 – O Capital Social é ilimitado quanto ao máximo e variável, conforme o número de quotas-partes subscritas, não podendo, porém, o valor ser inferior à R$ 5.000,00 (cinco mil reais). Parágrafo 1º – O Capital Social é dividido em quotas-partes de R$ 1,00(um real) cada uma, integralizável em duas parcelas de 50% (cinqüenta por cento) cada, em moeda corrente nacional, a primeira no ato da subscrição e a segunda em até um ano após a primeira. Parágrafo 2º – O associado ao ingressar na cooperativa se obriga a subscrever, 300 (trezentas) quotas-partes. " )), row.names = 1:2, class = "data.frame")
实现代码
之前用str_extract匹配失败核心是正则没有兼容两种章节开头格式(带TÍTULO前缀、直接罗马数字开头),也没有处理葡萄牙语的重音大写字符,用下面的代码可以直接实现需求:
library(stringr) library(dplyr) # 章节匹配正则:兼容带TÍTULO前缀、直接罗马数字开头两种格式,适配葡语重音字符 chapter_reg <- "(?<=^|\\n)\\s*(?:T[IÍ]TULO\\s+)?([IVXLCDM]+)\\s*\\n+([A-ZÇÃÁÉÍÓÚÂÔÊ\\s]+?)\\s*\\n+(?=[Aa]rt\\.)" # 单条文本拆分章节函数 split_single_text <- function(doc_id, raw_text) { match_pos <- str_locate_all(raw_text, chapter_reg)[[1]] if (nrow(match_pos) == 0) return(NULL) match_content <- str_match_all(raw_text, chapter_reg)[[1]] # 提取章节名、起止位置 chapter_names <- str_remove_all(match_content[,3], "\\s+") text_start <- match_pos[,2] + 1 text_end <- c(text_start[-1] - 1, nchar(raw_text)) # 逐段提取正文 chapter_df <- lapply(seq_along(chapter_names), function(i) { part_text <- str_sub(raw_text, start = text_start[i], end = text_end[i]) %>% str_trim() data.frame(ID = doc_id, chapter = chapter_names[i], text = part_text) }) %>% bind_rows() return(chapter_df) } # 批量处理所有文档 all_chapters <- lapply(1:nrow(df), function(i) split_single_text(df$ID[i], df$text[i])) %>% bind_rows() # 按章节拆分生成独立数据框到全局环境 chapter_dfs <- split(all_chapters, all_chapters$chapter) list2env(lapply(chapter_dfs, function(x) x[,c("ID", "text")]), envir = .GlobalEnv)
运行后全局环境会直接生成OBJETIVOS、DASASSEMBLÉIASGERAIS、DOCAPITALSOCIAL三个独立数据框,结构和预期完全一致。
内容的提问来源于stack exchange,提问作者RxT
相关产品推荐
相关产品推荐

