2014-11-26 6 views
5

Ich habe ein Stück Sätze und ich möchte die ungerichtete Kantenliste des Wortes Co-Auftreten und die Häufigkeit von jeder Kante zu sehen. Ich habe mir das tm Paket angeschaut, aber ähnliche Funktionen nicht gefunden. Gibt es ein Paket/Skript, das ich verwenden kann? Danke vielmals!Build Wort Co-Vorkommen Kantenliste in R

Hinweis: Ein Wort tritt nicht zusammen mit sich auf. Ein Wort, das zweimal oder öfter erscheint, kommt mit anderen Wörtern nur einmal im selben Satz vor.

DF:

sentence_id text 
1   a b c d e 
2   a b b e 
3   b c d 
4   a e 
5   a 
6   a a a 

OUTPUT

word1 word2 freq 
a  b  2 
a  c  1 
a  d  1 
a  e  3 
b  c  2 
b  d  2 
b  e  2 
c  d  2 
c  e  1 
d  e  1 
+0

@TylerRinker danke! Genau die Ausgabe sollte die gleiche bleiben wie Zeile 5 hat nur 'a' und in Zeile 6 'a' nicht mit sich selbst auftreten. – leoce

Antwort

2

Es gewunden ist so bekam es ein besserer Ansatz sein:

dat <- read.csv(text="sentence_id, text 
1,   a b c d e 
2,   a b b e 
3,   b c d 
4,   a e", header=TRUE) 


library(qdapTools); library(tidyr) 
x <- t(mtabulate(with(dat, by(text, sentence_id, bag_o_words))) > 0) 
out <- x %*% t(x) 
out[upper.tri(out, diag=TRUE)] <- NA 

out2 <- matrix2df(out, "word1") %>% 
    gather(word2, freq, -word1) %>% 
    na.omit() 

rownames(out2) <- NULL 
out2 

## word1 word2 freq 
## 1  b  a 2 
## 2  c  a 1 
## 3  d  a 1 
## 4  e  a 3 
## 5  c  b 2 
## 6  d  b 2 
## 7  e  b 2 
## 8  d  c 2 
## 9  e  c 1 
## 10  e  d 1 

Basis einzige Lösung

out <- lapply(with(dat, split(text, sentence_id)), function(x) { 
    strsplit(gsub("^\\s+|\\s+$", "", as.character(x)), "\\s+")[[1]] 
}) 

nms <- sort(unique(unlist(out))) 

out2 <- lapply(out, function(x) { 
    as.data.frame(table(x), stringsAsFactors = FALSE) 
}) 

dat2 <- data.frame(x = nms) 

for(i in seq_along(out2)) { 
    m <- merge(dat2, out2[[i]], all.x = TRUE) 
    names(m)[i + 1] <- dat[["sentence_id"]][i] 
    dat2 <- m 
} 

dat2[is.na(dat2)] <- 0 
x <- as.matrix(dat2[, -1]) > 0 

out3 <- x %*% t(x) 
out3[upper.tri(out3, diag=TRUE)] <- NA 
dimnames(out3) <- list(dat2[[1]], dat2[[1]]) 

out4 <- na.omit(data.frame( 
     word1 = rep(rownames(out3), ncol(out3)), 
     word2 = rep(colnames(out3), each = nrow(out3)), 
     freq = c(unlist(out3)), 
     stringsAsFactors = FALSE) 
) 

row.names(out4) <- NULL 

out4 
+0

Danke! Ihr Ansatz könnte für die zukünftige Forschung von anderen funktionieren. Meine Sätze sind jedoch tatsächlich auf Chinesisch und das Skript scheint nicht in der Lage zu sein, mit chinesischen Schriftzeichen umzugehen. Es hat alle Zeichen auf eine Weise in alphanumerische umgewandelt, die ich nicht verstehen kann. – leoce

+0

Können Sie spezifisch sein? Welcher Teil hat sie alphanumerisch gemacht? –

+0

Oh ich finde es heraus. Das Skript verwandelt chinesische Schriftzeichen in nichts, es lässt sie einfach weg. Die Zeilennamen der Matrix, die durch 'x <- t (mtabulate (mit (dat, by (text, satz_id, bag_o_words)))> 0) erzeugt werden, sind die englischen Wörter/Ziffern, die Teile der Sätze sind. – leoce

0

Hier ist eine Basis R Weg:

d <- read.table(text='sentence_id text 
1   "a b c d e" 
2   "a b b e" 
3   "b c d" 
4   "a e"', header=TRUE, as.is=TRUE) 

result.vec <- table(unlist(lapply(d$text, function(text) { 
    pairs <- combn(unique(scan(text=text, what='', sep=' ')), m=2) 
    interaction(pairs[1,], pairs[2,]) 
}))) 
# a.b b.b c.b d.b a.c b.c c.c d.c a.d b.d c.d d.d a.e b.e c.e d.e 
# 2 0 0 0 1 2 0 0 1 2 2 0 3 2 1 1 

result <- subset(data.frame(do.call(rbind, strsplit(names(result.vec), '\\.')), freq=as.vector(result.vec)), freq > 0) 
with(result, result[order(X1, X2),]) 

# X1 X2 freq 
# 1 a b 2 
# 5 a c 1 
# 9 a d 1 
# 13 a e 3 
# 6 b c 2 
# 10 b d 2 
# 14 b e 2 
# 11 c d 2 
# 15 c e 1 
# 16 d e 1 
+0

Danke! In realen Daten können jedoch 2 Probleme auftreten. Ich habe versucht und herausgefunden, dass das Skript 1-Wort-Sätze wie "hah" nicht entfernen kann. Wenn ein Satz mehrere Wörter hat, aber zu "1" (wie "hah hah hah") "einzigartig" wäre, würde die Konsole auch einen Fehler auslösen. – leoce

+0

Ich habe hier ein paar Zeilen hinzugefügt, um das Problem zu lösen: http://StackOverflow.com/Review/Suggested-Edits/6328674, danke! – leoce

1

Dies ist sehr eng verwandt mit @ TylerRinker Antwort, aber mit verschiedenen Werkzeugen.

library(splitstackshape) 
library(reshape2) 

temp <- crossprod(
    as.matrix(
    cSplit_e(d, "text", " ", type = "character", 
      fill = 0, drop = TRUE)[-1])) 
temp[upper.tri(temp, diag = TRUE)] <- NA 
melt(temp, na.rm = TRUE) 
#  Var1 Var2 value 
# 2 text_b text_a  2 
# 3 text_c text_a  1 
# 4 text_d text_a  1 
# 5 text_e text_a  3 
# 8 text_c text_b  2 
# 9 text_d text_b  2 
# 10 text_e text_b  2 
# 14 text_d text_c  2 
# 15 text_e text_c  1 
# 20 text_e text_d  1 

Die "text_" Teile "Var1" und "Var2" kann mit sub oder gsub leicht abgezogen werden.

+0

Ich mag es. Ich habe 'splitstackshape' heute in einer Antwort http://stackoverflow.com/a/27158031/1000343 herausgezogen, aber es hat keine Liebe :-( –

+0

der Ansatz scheint einfach und gerade, aber R kann die Funktion' cSplit' nicht finden, ' cSplit_e', oder 'cSplit_f' in der letzten Anleitung. Ich schätze, weil ich splitstackshape 1.2.0 (binäre Version) standardmäßig installiert habe, nicht 1.4.2 (Mac OSX 10.8.5, R 3.1.1) .packages ("splatstackshape", repos = "http://github.com/mrdwab/splitstackshape", type = "source") 'aber es heißt' package 'splitstapshape' ist nicht verfügbar (für R Version 3.1.1) ' – leoce

+0

@leoce, versuchen Sie es von CRAN zu installieren, aber mit 'type =" source ". Sie müssen das gleiche auch für" data.table "tun, vielleicht vor der Installation von" splitstapshape ". – A5C1D2H2I1M1N2O1R2T1