在 R 中:提取文本句子中的信息
In R : extract information in text sentence
我有一些文章的全文。我想提取一些信息(比如年份或月份)来分析它。
并以文章正文结构为例,
December 4, 2016 Sunday, LENGTH: (length of main text), HEADLINE: (the
title of article), BYLINE: (reporter name), BODY: (main text)
我把所有的文本都放在一行一行中。(所以我认为可以将文章结构视为一个字符串。)
在这种格式下,如何提取 LENGTH、HEADLINE、BYLINE 值并制作数据框?
我认为如果正确使用正则表达式是可能的,但我不知道具体如何。
这可能是一个开始:使用 strsplit
提取您需要的部分。这段代码有点乱,但它有效:
sentence <- "December 4, 2016 Sunday, LENGTH: 1070 words, HEADLINE: Korea presents new farm development model globally, BYLINE: By Yoon Ja-young"
Date <- as.character(sapply(strsplit(sentence, "LENGTH"), "[[",1))
Rows <- as.character(sapply(strsplit(sentence, "LENGTH"), "[[",2))
Length <- gsub(":","", as.character(sapply(strsplit(Rows, ","), "[[",1)))
Headline <- as.character(sapply(strsplit(as.character(sapply(strsplit(Rows, ","), "[[",2)), ":"), "[[",2))
Byline <- as.character(sapply(strsplit(as.character(sapply(strsplit(Rows, ","), "[[",3)), ":"), "[[",2))
然后收集数据框中的行:
Df <- data.frame(Date, Length, Headline, Byline)
希望以下解决方案对您有所帮助。我相信更有效的方法是可能的,查看 gsub
、grep
、stringr
.
DF<-data.frame(do.call(rbind, strsplit(x, ",", fixed=TRUE)))
DF$X1 <- paste(DF$X1,DF$X2, sep = ",")
new_df<-as.data.frame(lapply(DF, function(x) gsub(".*:", "", x)))
new_df<-subset(new_df, select = -X2)
colnames(new_df)<-c("Date","Length","Headline","ByLine","Other")
new_df
输出
Date Length Headline
1 December 4, 2016 Sunday 1070 words Korea presents new farm development model globally
2 Noveember 10, 2016 Friday 1070 words Korea presents new farm development model globally
ByLine Other
1 By Yoon Ja-young ~~~
2 By Yoon Ja-young ~~~
数据
x<- c("December 4, 2016 Sunday, LENGTH: 1070 words, HEADLINE: Korea
presents new farm development model globally, BYLINE: By Yoon Ja-young, BODY: ~~~",
"Noveember 10, 2016 Friday, LENGTH: 1070 words, HEADLINE: Korea
presents new farm development model globally, BYLINE: By Yoon Ja-young, BODY: ~~~")
更新: 正如@G.Grothendieck 评论中提到的那样,更改了将字段显示为列的解决方案。
首先可重复地定义测试数据——我们使用了问题中显示的两个数据实例。我们注意到棘手的部分是问题中的每条记录 运行 超过 1 行。
读入Lines
-- 用真实数据替换textConnection(Lines)
,也就是保留代码self-contained,用"myfile.txt"
,比如
然后第一个 sub
在每行的开头插入一个 space ,第二个替换所有包含 LENGTH: 的所有内容,包括 LENGTH: with newline, DATE:
、日期和 LENGTH:
。 gsub
在每个关键字前插入一个换行符,而 paste
将其全部折叠成一个大的换行符分隔字符串。 strsplit
再次拆分它,以便我们添加的换行符生效。
数据现在是 DCF 格式,因此我们可以使用 read.dcf
读取它。 DCF 格式用一个或多个空行分隔记录,每个字段以字段名开头,后跟冒号,space 后跟值。如果后续行缩进,该值可以 运行 到多行,例如以 space.
开头
这给出了一个包含 5 个指定列的矩阵。最后一个 sub
删除每个元素末尾的逗号,最后一个 gsub
将换行符替换为 spaces.
请注意,我们已将字段放置在列中,这通常是 R 中表示数据的方式,但如果您真的想要它在行中,请使用 t(dcf)
。
# test data
Lines <- "December 4, 2016 Sunday, LENGTH: 1070 words, HEADLINE: Korea presents new farm
development model globally, BYLINE: By Yoon Ja-young, BODY: ~~~
December 4, 2016 Sunday, LENGTH: 1070 words, HEADLINE: Korea presents new farm
development model globally, BYLINE: By Yoon Ja-young, BODY: ~~~"
# code
L0 <- readLines(textConnection(Lines))
L <- sub("^", " ", L0)
L <- sub("(.*) LENGTH:", "\nDATE: \1 LENGTH:", L)
L <- gsub("(\w+:)", "\n\1", L)
L <- paste(L, collapse = "\n")
L <- unlist(strsplit(L, "\n"))
dcf <- read.dcf(textConnection(L))
dcf[] <- sub(",$", "", dcf)
dcf[] <- gsub("\n", " ", dcf)
这给出了以下 5 列字符矩阵:
> dcf
DATE LENGTH
[1,] "December 4, 2016 Sunday" "1070 words"
[2,] "December 4, 2016 Sunday" "1070 words"
HEADLINE BYLINE
[1,] "Korea presents new farm development model globally" "By Yoon Ja-young"
[2,] "Korea presents new farm development model globally" "By Yoon Ja-young"
BODY
[1,] "~~~"
[2,] "~~~"
更新: 添加了输出日期。
这是一个在基本 R 包中使用字符串拆分和一些正则表达式的答案。只要数据始终采用显示的格式,它就可以工作。
data <- "December 4, 2016 Sunday, LENGTH: 1070 words, HEADLINE: Korea presents new farm development model globally, BYLINE: By Yoon Ja-young, BODY: ~~~"
textParse <- function(dat){
tmp <- strsplit(dat, ', ')[[1]]
time <- as.Date(paste(tmp[1:2], collapse = ' '), format="%B %d %Y")
len <- strsplit(gsub(".*LENGTH: (\d+)", "\1", dat), " ")[[1]][1]
headline <- paste(strsplit(tmp[4], ' ')[[1]][2:length(strsplit(tmp[4], ' ')[[1]])], collapse = ' ')
byline <- paste(strsplit(tmp[5], ' ')[[1]][3:length(strsplit(tmp[5], ' ')[[1]])], collapse = ' ')
body <- paste(strsplit(tmp[6], ' ')[[1]][2:length(strsplit(tmp[6], ' ')[[1]])], collapse = ' ')
return(as.data.frame(cbind(time, len, headline, byline, body)))
}
textParse(data)
输出:
time len headline byline
1 17139 1070 Korea presents new farm development model globally Yoon Ja-young
body
1 ~~~
编辑:请注意,R 中的时间表示为 "the number of days since 1970-01-01" R: Date-time Conversion
的整数
我有一些文章的全文。我想提取一些信息(比如年份或月份)来分析它。
并以文章正文结构为例,
December 4, 2016 Sunday, LENGTH: (length of main text), HEADLINE: (the title of article), BYLINE: (reporter name), BODY: (main text)
我把所有的文本都放在一行一行中。(所以我认为可以将文章结构视为一个字符串。)
在这种格式下,如何提取 LENGTH、HEADLINE、BYLINE 值并制作数据框?
我认为如果正确使用正则表达式是可能的,但我不知道具体如何。
这可能是一个开始:使用 strsplit
提取您需要的部分。这段代码有点乱,但它有效:
sentence <- "December 4, 2016 Sunday, LENGTH: 1070 words, HEADLINE: Korea presents new farm development model globally, BYLINE: By Yoon Ja-young"
Date <- as.character(sapply(strsplit(sentence, "LENGTH"), "[[",1))
Rows <- as.character(sapply(strsplit(sentence, "LENGTH"), "[[",2))
Length <- gsub(":","", as.character(sapply(strsplit(Rows, ","), "[[",1)))
Headline <- as.character(sapply(strsplit(as.character(sapply(strsplit(Rows, ","), "[[",2)), ":"), "[[",2))
Byline <- as.character(sapply(strsplit(as.character(sapply(strsplit(Rows, ","), "[[",3)), ":"), "[[",2))
然后收集数据框中的行:
Df <- data.frame(Date, Length, Headline, Byline)
希望以下解决方案对您有所帮助。我相信更有效的方法是可能的,查看 gsub
、grep
、stringr
.
DF<-data.frame(do.call(rbind, strsplit(x, ",", fixed=TRUE)))
DF$X1 <- paste(DF$X1,DF$X2, sep = ",")
new_df<-as.data.frame(lapply(DF, function(x) gsub(".*:", "", x)))
new_df<-subset(new_df, select = -X2)
colnames(new_df)<-c("Date","Length","Headline","ByLine","Other")
new_df
输出
Date Length Headline
1 December 4, 2016 Sunday 1070 words Korea presents new farm development model globally
2 Noveember 10, 2016 Friday 1070 words Korea presents new farm development model globally
ByLine Other
1 By Yoon Ja-young ~~~
2 By Yoon Ja-young ~~~
数据
x<- c("December 4, 2016 Sunday, LENGTH: 1070 words, HEADLINE: Korea
presents new farm development model globally, BYLINE: By Yoon Ja-young, BODY: ~~~",
"Noveember 10, 2016 Friday, LENGTH: 1070 words, HEADLINE: Korea
presents new farm development model globally, BYLINE: By Yoon Ja-young, BODY: ~~~")
更新: 正如@G.Grothendieck 评论中提到的那样,更改了将字段显示为列的解决方案。
首先可重复地定义测试数据——我们使用了问题中显示的两个数据实例。我们注意到棘手的部分是问题中的每条记录 运行 超过 1 行。
读入Lines
-- 用真实数据替换textConnection(Lines)
,也就是保留代码self-contained,用"myfile.txt"
,比如
然后第一个 sub
在每行的开头插入一个 space ,第二个替换所有包含 LENGTH: 的所有内容,包括 LENGTH: with newline, DATE:
、日期和 LENGTH:
。 gsub
在每个关键字前插入一个换行符,而 paste
将其全部折叠成一个大的换行符分隔字符串。 strsplit
再次拆分它,以便我们添加的换行符生效。
数据现在是 DCF 格式,因此我们可以使用 read.dcf
读取它。 DCF 格式用一个或多个空行分隔记录,每个字段以字段名开头,后跟冒号,space 后跟值。如果后续行缩进,该值可以 运行 到多行,例如以 space.
这给出了一个包含 5 个指定列的矩阵。最后一个 sub
删除每个元素末尾的逗号,最后一个 gsub
将换行符替换为 spaces.
请注意,我们已将字段放置在列中,这通常是 R 中表示数据的方式,但如果您真的想要它在行中,请使用 t(dcf)
。
# test data
Lines <- "December 4, 2016 Sunday, LENGTH: 1070 words, HEADLINE: Korea presents new farm
development model globally, BYLINE: By Yoon Ja-young, BODY: ~~~
December 4, 2016 Sunday, LENGTH: 1070 words, HEADLINE: Korea presents new farm
development model globally, BYLINE: By Yoon Ja-young, BODY: ~~~"
# code
L0 <- readLines(textConnection(Lines))
L <- sub("^", " ", L0)
L <- sub("(.*) LENGTH:", "\nDATE: \1 LENGTH:", L)
L <- gsub("(\w+:)", "\n\1", L)
L <- paste(L, collapse = "\n")
L <- unlist(strsplit(L, "\n"))
dcf <- read.dcf(textConnection(L))
dcf[] <- sub(",$", "", dcf)
dcf[] <- gsub("\n", " ", dcf)
这给出了以下 5 列字符矩阵:
> dcf
DATE LENGTH
[1,] "December 4, 2016 Sunday" "1070 words"
[2,] "December 4, 2016 Sunday" "1070 words"
HEADLINE BYLINE
[1,] "Korea presents new farm development model globally" "By Yoon Ja-young"
[2,] "Korea presents new farm development model globally" "By Yoon Ja-young"
BODY
[1,] "~~~"
[2,] "~~~"
更新: 添加了输出日期。
这是一个在基本 R 包中使用字符串拆分和一些正则表达式的答案。只要数据始终采用显示的格式,它就可以工作。
data <- "December 4, 2016 Sunday, LENGTH: 1070 words, HEADLINE: Korea presents new farm development model globally, BYLINE: By Yoon Ja-young, BODY: ~~~"
textParse <- function(dat){
tmp <- strsplit(dat, ', ')[[1]]
time <- as.Date(paste(tmp[1:2], collapse = ' '), format="%B %d %Y")
len <- strsplit(gsub(".*LENGTH: (\d+)", "\1", dat), " ")[[1]][1]
headline <- paste(strsplit(tmp[4], ' ')[[1]][2:length(strsplit(tmp[4], ' ')[[1]])], collapse = ' ')
byline <- paste(strsplit(tmp[5], ' ')[[1]][3:length(strsplit(tmp[5], ' ')[[1]])], collapse = ' ')
body <- paste(strsplit(tmp[6], ' ')[[1]][2:length(strsplit(tmp[6], ' ')[[1]])], collapse = ' ')
return(as.data.frame(cbind(time, len, headline, byline, body)))
}
textParse(data)
输出:
time len headline byline
1 17139 1070 Korea presents new farm development model globally Yoon Ja-young
body
1 ~~~
编辑:请注意,R 中的时间表示为 "the number of days since 1970-01-01" R: Date-time Conversion
的整数