从文本中提取名词+名词或(形容词|名词)+名词

8

使用R包openNLP是否可以提取noun+noun(adj|noun)+noun?也就是说,我想使用语言过滤器提取候选名词短语。您能指导我如何操作吗? 非常感谢。


谢谢回复。 以下是代码:

library("openNLP")

acq <- "Gulf Applied Technologies Inc said it sold its subsidiaries engaged in
        pipeline and terminal operations for 12.2 mln dlrs. The company said 
        the sale is subject to certain post closing adjustments, 
        which it did not explain. Reuter." 

acqTag <- tagPOS(acq)    
acqTagSplit = strsplit(acqTag," ")
acqTagSplit

qq = 0
tag = 0

for (i in 1:length(acqTagSplit[[1]])){
    qq[i] <-strsplit(acqTagSplit[[1]][i],'/')
    tag[i] = qq[i][[1]][2]
}

index = 0

k = 0

for (i in 1:(length(acqTagSplit[[1]])-1)) {
    
    if ((tag[i] == "NN" && tag[i+1] == "NN") | 
        (tag[i] == "NNS" && tag[i+1] == "NNS") | 
        (tag[i] == "NNS" && tag[i+1] == "NN") | 
        (tag[i] == "NN" && tag[i+1] == "NNS") | 
        (tag[i] == "JJ" && tag[i+1] == "NN") | 
        (tag[i] == "JJ" && tag[i+1] == "NNS"))
    {      
            k = k +1
            index[k] = i
    }

}

index

读者可以参考 acqTagSplit 上的索引来进行noun+noun(adj|noun)+noun提取。(该代码不是最优的,但它能够工作。如果您有任何想法,请告诉我。)

我还有一个额外的问题:

Justeson和Katz(1995)提出了另一种语言过滤方法来提取候选名词短语:

((Adj|Noun)+|((Adj|Noun)*(Noun-Prep)?)(Adj|Noun)*)Noun

我无法很好地理解它的含义。你能帮我解释一下吗?或者展示如何在R语言中编写过滤规则?非常感谢。


1
我发布了我认为是一个干净的解决方案。你后来的请求是原始问题的相当扩展。我认为你应该关闭这个问题并提出另一个问题。 - IRTFM
1
@DWin:我认为不是这样。它只是增加了一些额外的条件。此外,将其翻译成R语言是一个文本挖掘者而非程序员的问题。我建议ssuhan阅读Justeson和Katz的文章以理解它的含义。 - Joris Meys
1
@Joris:有几个我不理解的新操作符 "+" 和 "?"。我认为它们可能以某种方式转换为正则表达式,但我无从得知,而且在网上搜索也找不到相关引用。因此,我认为重新发布问题会更好,因为原始问题已经得到了提问者和我的努力优化的答案。 - IRTFM
2个回答

5

我没有一个开放的控制台来测试这个,但你是否尝试过使用tagPOS进行标记化,然后使用grep查找“名词”,“名词”,或者可能是paste(tagPOS(acq), collapse=".")并搜索“名词.名词”。然后可以使用gregexpr提取位置。

编辑:标记输出的格式与我记得的有点不同。我认为在用空格替换"\n"之后使用read.table()方法更高效,比上面看到的方法更好:

 acqdf <- read.table(textConnection(gsub(" ", "\n", acqTag)), sep="/", stringsAsFactors=FALSE)
 acqdf$nnadj <- grepl("NN|JJ", acqdf$V2)
 acqdf$nnadj 
# [1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE  TRUE
#[16] FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE
#[31]  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE
 acqdf$nnadj[1:(nrow(acqdf)-1)] & acqdf$nnadj[2:nrow(acqdf)]
# [1]  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
#[16] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE
#[31] FALSE FALSE FALSE FALSE FALSE FALSE
 acqdf$pair <- c(NA, acqdf$nnadj[1:(nrow(acqdf)-1)] & acqdf$nnadj[2:nrow(acqdf)])
 acqdf[1:7, ]

            V1  V2 nnadj  pair
1         Gulf NNP  TRUE    NA
2      Applied NNP  TRUE  TRUE
3 Technologies NNP  TRUE  TRUE
4          Inc NNP  TRUE  TRUE
5         said VBD FALSE FALSE
6           it PRP FALSE FALSE
7         sold VBD FALSE FALSE

谢谢回答。你的想法很吸引我。但是我还是R的初学者。请问你能否给我更详细的指导?非常感谢。 - ssuhan
谢谢DWin。你太棒了!(点赞) - ssuhan

3

这是可能的。

编辑:

你做到了。使用POS标记器并在空格上分割:ll <- strsplit(acqTag,' ')。从那里开始迭代输入列表的长度(ll的长度),如: for (i in 1:37){qq <-strsplit(ll[[1]][i],'/')} 并获取您要查找的词性序列。

在空格上分割后,只需在R中进行列表处理。


谢谢carlosdc。你可以给我一些编写此类进程的指导吗? - ssuhan
谢谢carlosdc。我按照你的指示编写了一些代码。你能再给我一些建议吗?非常感谢。 - ssuhan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接