I want to create a bag of bigrams in a set of documents and calculate the TF-IDF vector of each document. To calculate the bigram of the text I used the following code: The small example of the data (each element in the list is a different document)
data = {"The food at snack is a selection of popular Greek dishes.
The appetizer tray is good as is the Greek salad. We were underwhelmed with
the main courses. There are 4-5 tables here so it's
sometimes hard to get seated.","This little place in Soho is wonderful. I
had
a lamb sandwich and a glass of wine. The price shocked me for how small the
serving was, but then again, this is Soho. The staff can be a little snotty
and rude, but the food is great, just don't expect world-class service.",
"ordered lunch for 15 from Snack last Friday. On time, nothing
missing and the food was great. I have added it to the regular
company lunch list, as everyone enjoyed their meal."}
The way that I create the bigrams in the file (set of documents) and calculate the TF for each bigram in specific document:
bigram =
Table[
Merge[
<|First[#] <> " " <> Last[#] -> 1|> & /@
Partition[
StringSplit[StringReplace[data[[i]], PunctuationCharacter ->""]],
2, 1],
Total],
{i, 1, Length@data}]
The way that I calculate the frequency of the bigrams in the file (ITF):
bigramUniqe = <||>
Scan[(If[MissingQ[bigramUniqe[#]], AssociateTo[bigramUniqe, # -> 1],
AssociateTo[bigramUniqe, # -> (bigramUniqe[#] + 1)]]) &, bigram];
But in this way, I do not succeed to count the frequency of document that contains the specific bigrams( I have some issue with the level specification of the Associate). Anyway, I look for a more efficient way to implement this task.Thank in advance for any suggestions.
Answer
What do you think about skipping the StringJoin
and storing a bigram as a pair of strings?
getbigrams[text_String] := Module[{words},
words =
StringSplit[
ToLowerCase[StringDelete[text, PunctuationCharacter]]];
Counts[Partition[words, 2, 1]]
]
That can save about 40 % of time:
data = ExampleData /@ ExampleData["Text"];
a = Table[
Merge[<|First[#] <> " " <> Last[#] -> 1|> & /@
Partition[
StringSplit[
StringReplace[ToLowerCase[data[[i]]],
PunctuationCharacter -> ""]], 2, 1], Total], {i, 1,
Length@data}]; // AbsoluteTiming // First
b = getbigrams /@ data; // AbsoluteTiming // First
Values[a] == Values[b]
7.62668
4.40748
True
Comments
Post a Comment