2015-09-13 13 views
7

Ho un vettore come quello sotto e vorrei determinare quali elementi nell'elenco sono nomi umani e quali no. Ho trovato il pacchetto humaniformat, che formatta i nomi ma sfortunatamente non determina se una stringa è in realtà un nome. Ho anche trovato alcuni pacchetti per l'estrazione delle entità, ma sembrano richiedere un testo reale per la codifica della parte del discorso, piuttosto che un singolo nome.Da un elenco di stringhe, identificare quali sono nomi umani e quali non sono

Esempio

pkd.names.quotes <- c("Mr. Rick Deckard", # Name 
         "Do Androids Dream of Electric Sheep", # Not a name 
         "Roy Batty", # Name 
         "How much is an electric ostrich?", # Not a name 
         "My schedule for today lists a six-hour self-accusatory depression.", # Not a name 
         "Upon him the contempt of three planets descended.", # Not a name 
         "J.F. Sebastian", # Name 
         "Harry Bryant", # Name 
         "goat class", # Not a name 
         "Holden, Dave", # Name 
         "Leon Kowalski", # Name 
         "Dr. Eldon Tyrell") # Name 
+5

Il mio amico Electric Ostrich sarebbe terribilmente sconvolto nel vedere che il suo nome non è proprio un nome. Quindi dovrai sapere cosa determina esattamente un nome, corretto? Ma al giorno d'oggi le persone chiamano i loro figli quasi tutto (in America comunque). Prendi il figlio di Kanye West per esempio. Il suo nome è North West. Certo, Kanye è un idiota, questo è ancora vero. Come passerebbe il test del nome? –

+0

Haha, abbastanza giusto. Suppongo che avrei sbagliato i nomi dei bambini di Kanye. Va bene però, qualche errore è accettabile. Spero solo di fare meglio del semplice affidamento su lunghezza della stringa, numero di spazi e lettere maiuscole. –

+1

Il "modulo" Stanford Named Entity Recognition è disponibile per R. https://rpubs.com/lmullen/nlp-chapter ha un'intestazione NLP. Questo http://nlp.stanford.edu/software/CRF-NER.shtml è la fonte ufficiale di java lib e potrebbe essere possibile creare una soluzione da esso. – hrbrmstr

risposta

11

Ecco un approccio. Lo US Census Bureau tabula un elenco di cognomi che si verificano> 100 volte nel suo database (con frequenza): tutti 152.000 di essi. Se si utilizza l'elenco completo, tutte le stringhe hanno un nome. Ad esempio, "class", "him" e "the" sono nomi in alcune lingue (non sono sicuro quali siano le lingue). Allo stesso modo, ci sono molti elenchi di nomi (vedi this post).

Il codice seguente preleva tutti i cognomi dal censimento 2000 e un elenco di nomi primi dal post citato, quindi passa ai 10.000 più comuni in ogni elenco, combina e pulisce gli elenchi e lo utilizza come dizionario nel pacchetto tm per identificare quali stringhe contengono nomi. È possibile controllare la "sensibilità" alterando la variabile freq (freq = 10.000 sembra generare il risultato desiderato).

url <- "http://www2.census.gov/topics/genealogy/2000surnames/names.zip" 
tf <- tempfile() 
download.file(url,tf, mode="wb")      # download archive of surname data 
files <- unzip(tf, exdir=tempdir())    # unzips and returns a vector of file names 
surnames <- read.csv(files[grepl("\\.csv$",files)]) # 152,000 surnames occurring >100 times 
url <- "http://deron.meranda.us/data/census-derived-all-first.txt" 
firstnames <- read.table(url(url), header=FALSE) 
freq <- 10000 
dict <- unique(c(tolower(surnames$name[1:freq]), tolower(firstnames$V1[1:freq]))) 
library(tm) 
corp <- Corpus(VectorSource(pkd.names.quotes)) 
tdm <- TermDocumentMatrix(corp, control=list(tolower=TRUE, dictionary=dict)) 
m <- as.matrix(tdm) 
m <- m[rowSums(m)>0,] 
m 
#   Docs 
# Terms  1 2 3 4 5 6 7 8 9 10 11 12 
# bryant 0 0 0 0 0 0 0 1 0 0 0 0 
# dave  0 0 0 0 0 0 0 0 0 1 0 0 
# deckard 1 0 0 0 0 0 0 0 0 0 0 0 
# eldon  0 0 0 0 0 0 0 0 0 0 0 1 
# harry  0 0 0 0 0 0 0 1 0 0 0 0 
# kowalski 0 0 0 0 0 0 0 0 0 0 1 0 
# leon  0 0 0 0 0 0 0 0 0 0 1 0 
# rick  1 0 0 0 0 0 0 0 0 0 0 0 
# roy  0 0 1 0 0 0 0 0 0 0 0 0 
# sebastian 0 0 0 0 0 0 1 0 0 0 0 0 
# tyrell 0 0 0 0 0 0 0 0 0 0 0 1 
which(colSums(m)>0) 
# 1 3 7 8 10 11 12 
Problemi correlati