我有一个很大的数据框,其中包含推文和关键字字典,这些字典作为具有与道德(kw_Moral
)和情感(kw_Emo
)相关的单词的值加载。过去,我使用关键字字典对数据框进行子集设置,以仅获取包含一个或多个关键字的推文。
例如,要创建一个仅包含具有情感关键词的推文的子集,我将其加载到我的关键词词典中...
kw_Emo <- c("abusi*", "accept", "accepta*", "accepted",
"accepting", "accepts", "ache*", "aching", "active*", "admir*",
"ador*", "advantag*", "adventur*", "advers*", "affection*", "afraid",
"aggravat*", "aggress*", "agoniz*", "agony", "agree", "agreeab*",
"agreed", "agreeing", "agreement*", "agrees", "alarm*", "alone",
"alright*", "amaz*", "amor*", "amus*", "anger*", "angr*", "anguish*",
"annoy*", "antagoni*", "anxi*", "aok", "apath*", "appall*", "appreciat*",
"apprehens*", "argh*", "argu*", "arrogan*", "asham*", "assault*",
"asshole*", "assur*", "attachment*", "attract*", "aversi*", "avoid*",
"award*", "awesome", "awful", "awkward*", "bashful*", "bastard*",
"battl*", "beaten", "beaut*", "beloved", "benefic*", "benevolen*",
"benign*", "best", "better", "bitch*", "bitter*", "blam*", "bless*",
"bold*", "bonus*", "bore*", "boring", "bother*", "brave*", "bright*",
"brillian*", "broke", "burden*", "calm*", "cared", "carefree",
"careful*", "careless*", "cares", "casual", "casually", "certain*",
"challeng*", "champ*", "charit*", "charm*", "cheer*", "cherish*",
"chuckl*", "clever*", "comed*", "comfort*", "commitment*", "complain*",
"compliment*", "concerned", "confidence", "confident", "confidently",
"confront*", "confus*", "considerate", "contempt*", "contented*",
"contentment", "contradic*", "convinc*", "cool", "courag*", "crap",
"crappy", "craz*", "create*", "creati*", "credit*", "cried",
"cries", "critical", "critici*", "crude*", "cry", "crying", "cunt*",
"cut", "cute*", "cutie*", "cynic", "danger*", "daring", "darlin*",
"daze*", "dear*", "decay*", "defeat*", "defect*", "definite",
"definitely", "degrad*", "delectabl*", "delicate*", "delicious*",
"deligh*", "depress*", "depriv*", "despair*", "desperat*", "despis*",
"destruct*", "determina*", "determined", "devastat*", "difficult*",
"digni*", "disadvantage*", "disagree*", "disappoint*", "disaster*",
"discomfort*", "discourag*", "dishearten*", "disillusion*", "dislike",
"disliked", "dislikes", "disliking", "dismay*", "dissatisf*",
"distract*", "distraught", "distress*", "distrust*", "disturb*",
"divin*", "domina*", "doom*", "dork*", "doubt*", "dread*", "dull*",
"dumb*", "dump*", "dwell*", "dynam*", "eager*", "ease*", "easie*",
"easily", "easiness", "easing", "easy*", "ecsta*", "efficien*",
"egotis*", "elegan*", "embarrass*", "emotion", "emotional", "empt*",
"encourag*", "energ*", "engag*", "enjoy*", "enrag*", "entertain*",
"enthus*", "envie*", "envious", "excel*", "excit*", "excruciat*",
"exhaust*", "fab", "fabulous*", "fail*", "fake", "fantastic*",
"fatal*", "fatigu*", "favor*", "favour*", "fear", "feared", "fearful*",
"fearing", "fearless*", "fears", "feroc*", "festiv*", "feud*",
"fiery", "fiesta*", "fine", "fired", "flatter*", "flawless*",
"flexib*", "flirt*", "flunk*", "foe*", "fond", "fondly", "fondness",
"fool*", "forgave", "forgiv*", "fought", "frantic*", "freak*",
"free", "freeb*", "freed*", "freeing", "freely", "freeness",
"freer", "frees*", "friend*", "fright*", "frustrat*", "fuck",
"fucked*", "fucker*", "fuckin*", "fucks", "fume*", "fuming",
"fun", "funn*", "furious*", "fury", "geek*", "genero*", "gentle",
"gentler", "gentlest", "gently", "giggl*", "giver*", "giving",
"glad", "gladly", "glamor*", "glamour*", "gloom*", "glori*",
"glory", "goddam*", "gorgeous*", "gossip*", "grace", "graced",
"graceful*", "graces", "graci*", "grand", "grande*", "gratef*",
"grati*", "grave*", "great", "grief", "griev*", "grim*", "grin",
"grinn*", "grins", "grouch*", "grr*", "guilt*", "ha", "haha*",
"handsom*", "happi*", "happy", "harass*", "hated", "hateful*",
"hater*", "hates", "hating", "hatred", "hazy", "heartbreak*",
"heartbroke*", "heartfelt", "heartless*", "heartwarm*", "heh*",
"hellish", "helper*", "helpful*", "helping", "helpless*", "helps",
"hesita*", "hilarious", "hoho*", "homesick*", "honour*", "hope",
"hoped", "hopeful", "hopefully", "hopefulness", "hopeless*",
"hopes", "hoping", "horr*", "hostil*", "hug", "hugg*", "hugs",
"humiliat*", "humor*", "humour*", "hurra*", "idiot", "ignor*",
"impatien*", "impersonal", "impolite*", "importan*", "impress*",
"improve*", "improving", "inadequa*", "incentive*", "indecis*",
"ineffect*", "inferior*", "inhib*", "innocen*", "insecur*", "insincer*",
"inspir*", "insult*", "intell*", "interest*", "interrup*", "intimidat*",
"invigor*", "irrational*", "irrita*", "isolat*", "jaded", "jealous*",
"jerk", "jerked", "jerks", "joke*", "joking", "joll*", "joy*",
"keen*", "kidding", "kind", "kindly", "kindn*", "kiss*", "laidback",
"lame*", "laugh*", "lazie*", "lazy", "liabilit*", "libert*",
"lied", "lies", "like", "likeab*", "liked", "likes", "liking",
"livel*", "LMAO", "LOL", "lone*", "longing*", "lose", "loser*",
"loses", "losing", "loss*", "lost", "lous*", "love", "loved",
"lovely", "lover*", "loves", "loving*", "low*", "luck", "lucked",
"lucki*", "luckless*", "lucks", "lucky", "ludicrous*", "lying",
"mad", "maddening", "madder", "maddest", "madly", "magnific*",
"maniac*", "masochis*", "melanchol*", "merit*", "merr*", "mess",
"messy", "miser*", "miss", "missed", "misses", "missing", "mistak*",
"mock", "mocked", "mocker*", "mocking", "mocks", "molest*", "mooch*",
"mood", "moodi*", "moods", "moody", "moron*", "mourn*", "nag*",
"nast*", "neat*", "needy", "neglect*", "nerd*", "nervous*", "neurotic*",
"nice*", "numb*", "nurtur*", "obnoxious*", "obsess*", "offence*",
"offens*", "ok", "okay", "okays", "oks", "openminded*", "openness",
"opportun*", "optimal*", "optimi*", "original", "outgoing", "outrag*",
"overwhelm*", "pained", "painf*", "paining", "painl*", "pains",
"palatabl*", "panic*", "paradise", "paranoi*", "partie*", "party*",
"passion*", "pathetic*", "peculiar*", "perfect*", "personal",
"perver*", "pessimis*", "petrif*", "pettie*", "petty*", "phobi*",
"piss*", "piti*", "pity*", "play", "played", "playful*", "playing",
"plays", "pleasant*", "please*", "pleasing", "pleasur*", "poison*",
"popular*", "positiv*", "prais*", "precious*", "pressur*", "prettie*",
"pretty", "prick*", "pride", "privileg*", "prize*", "problem*",
"profit*", "promis*", "protested", "protesting", "proud*", "puk*",
"radian*", "rage*", "raging", "rancid*", "rape*", "raping", "rapist*",
"readiness", "ready", "reassur*", "reek*", "regret*", "reject*",
"relax*", "relief", "reliev*", "reluctan*", "remorse*", "repress*",
"resent*", "resign*", "resolv*", "restless*", "revigor*", "reward*",
"rich*", "ridicul*", "rigid*", "risk*", "ROFL", "romanc*", "romantic*",
"rotten", "rude*", "sad", "sadde*", "sadly", "sadness", "sarcas*",
"satisf*", "savage*", "scare*", "scaring", "scary", "sceptic*",
"scream*", "screw*", "selfish*", "sentimental*", "serious", "seriously",
"seriousness", "severe*", "shake*", "shaki*", "shaky", "share",
"shared", "shares", "sharing", "shit*", "shock*", "shook", "shy*",
"sigh", "sighed", "sighing", "sighs", "silli*", "silly", "sincer*",
"skeptic*", "smart*", "smil*", "smother*", "smug*", "snob*",
"sob", "sobbed", "sobbing", "sobs", "sociab*", "solemn*", "sorrow*",
"sorry", "soulmate*", "special", "splend*", "stammer*", "stank",
"startl*", "stink*", "strain*", "strange", "strength*", "stress*",
"strong*", "struggl*", "stubborn*", "stunk", "stunned", "stuns",
"stupid*", "stutter*", "succeed*", "success*", "suck", "sucked",
"sucker*", "sucks", "sucky", "sunnier", "sunniest", "sunny",
"sunshin*", "super", "superior*", "support", "supported", "supporter*",
"supporting", "supportive*", "supports", "suprem*", "sure*",
"surpris*", "suspicio*", "sweet", "sweetheart*", "sweetie*",
"sweetly", "sweetness*", "sweets", "talent*", "tantrum*", "tears",
"teas*", "tehe", "temper", "tempers", "tender*", "tense*", "tensing",
"tension*", "terribl*", "terrific*", "terrified", "terrifies",
"terrify", "terrifying", "terror*", "thank", "thanked", "thankf*",
"thanks", "thief", "thieve*", "thoughtful*", "threat*", "thrill*",
"ticked", "timid*", "toleran*", "tortur*", "tough*", "traged*",
"tragic*", "tranquil*", "trauma*", "treasur*", "treat", "trembl*",
"trick*", "trite", "triumph*", "trivi*", "troubl*", "TRUE", "trueness",
"truer", "truest", "truly", "trust*", "truth*", "turmoil", "ugh",
"ugl*", "unattractive", "uncertain*", "uncomfortabl*", "uncontrol*",
"uneas*", "unfortunate*", "unfriendly", "ungrateful*", "unhapp*",
"unimportant", "unimpress*", "unkind", "unlov*", "unpleasant",
"unprotected", "unsavo*", "unsuccessful*", "unsure*", "unwelcom*",
"upset*", "uptight*", "useful*", "useless*", "vain", "valuabl*",
"valuing", "vanity", "vicious*", "vigor*", "vigour*", "villain*",
"violat*", "virtuo*", "vital*", "vulnerab*", "vulture*", "warfare*",
"warm*", "warred", "weak*", "wealth*", "weapon*", "weep*", "weird*",
"welcom*", "well*", "wept", "whine*", "whining", "willing", "wimp*",
"win", "winn*", "wins", "wisdom", "wise*", "witch", "woe*", "won",
"wonderf*", "worr*", "worse*", "worship*", "worst", "wow*", "yay",
"yays","yearn*","stench*") %>% paste0(collapse="|")and then filtered my dataframe with the keywords...
tweets_E <- tweets[with(tweets, grepl(paste0("\\b(?:",paste(kw_Emo, collapse="|"),")\\b"), text)),]
如何扩展此过程以准确计算每个推文中出现了多少个词典单词?换句话说,我想向数据帧添加一个向量,例如{{1} },它将显示每条推文中出现的情感词的数量。
这是我的数据的可复制样本:
EmoWordCount
dput(droplevels(head(TestTweets, 20)))
这是我从弗朗西斯科使用的代码:
structure(list(Time = c("24/06/2016 10:55:04", "24/06/2016 10:55:04",
"24/06/2016 10:55:04", "24/06/2016 10:55:04", "24/06/2016 10:55:04",
"24/06/2016 10:55:04", "24/06/2016 10:55:04", "24/06/2016 10:55:04",
"24/06/2016 10:55:04", "24/06/2016 10:55:04", "24/06/2016 10:55:04",
"24/06/2016 10:55:04", "24/06/2016 10:55:04", "24/06/2016 10:55:04",
"24/06/2016 10:55:04", "24/06/2016 10:55:04", "24/06/2016 10:55:04",
"24/06/2016 10:55:04", "24/06/2016 10:55:03", "24/06/2016 10:55:03"
), clean_text = c("mayagoodfellow as always making sense of it all for us ive never felt less welcome in this country brexit httpstcoiai5xa9ywv",
"never underestimate power of stupid people in a democracy brexit",
"a quick guide to brexit and beyond after britain votes to quit eu httpstcos1xkzrumvg httpstcocniutojkt0",
"this selfinflicted wound will be his legacy cameron falls on sword after brexit euref httpstcoegph3qonbj httpstcohbyhxodeda",
"so the uk is out cameron resigned scotland wants to leave great britain sinn fein plans to unify ireland and its o",
"this is a very good summary no biasspinagenda of the legal ramifications of the leave result brexit httpstcolobtyo48ng",
"you cant make this up cornwall votes out immediately pleads to keep eu cash this was never a rehearsal httpstco",
"no matter the outcome brexit polls demonstrate how quickly half of any population can be convinced to vote against itself q",
"i wouldnt mind so much but the result is based on a pack of lies and unaccountable promises democracy didnt win brexit pro",
"so the uk is out cameron resigned scotland wants to leave great britain sinn fein plans to unify ireland and its o",
"absolutely brilliant poll on brexit by yougov httpstcoepevg1moaw",
"retweeted mikhail golub golub\r\n\r\nbrexit to be followed by grexit departugal italeave fruckoff czechout httpstcoavkpfesddz",
"think the brexit campaign relies on the same sort of logic that drpepper does whats the worst that can happen thingsthatarewellbrexit",
"am baffled by nigel farages claim that brexit is a victory for real people as if the 47 voting remain are fucking smu",
"not one of the uks problems has been solved by brexit vote migration inequality the uks centurylong decline as",
"scotland should never leave eu calls for new independence vote grow httpstcorudiyvthia brexit",
"the most articulate take on brexit is actually this ft reader comment today httpstco98b4dwsrtv",
"65 million refugees half of them are children maybe instead of fighting each other we should be working hand in hand ",
"im laughing at people who voted for brexit but are complaining about the exchange rate affecting their holiday\r\nremain",
"life is too short to wear boring shoes brexit")), .Names = c("Time",
"clean_text"), row.names = c(NA, 20L), class = c("tbl_df", "tbl",
"data.frame"))
以下是弗朗西斯科解决方案的输出(我将新列重命名为library(stringr)
for (x in 1:length(kw_Emo)) {
if (grepl("[*]", kw_Emo[x]) == TRUE) {
kw_Emo[x] <- substr(kw_Emo[x],1,nchar(kw_Emo[x])-1)
}
}
for (x in 1:length(kw_Emo)) {
TestTweets[, kw_Emo[x]] <- 0
}
for (x in 1:nrow(TestTweets)) {
partials <- data.frame(str_split(TestTweets[x,2], " "), stringsAsFactors=FALSE)
partials <- partials[partials[] != ""]
for(y in 1:length(partials)) {
for (z in 1:length(kw_Emo)) {
if (kw_Emo[z] == partials[y]) {
TestTweets[x, kw_Emo[z]] <- TestTweets[x, kw_Emo[z]] + 1
}
}
}
}
):
EmoWordCount
答案 0 :(得分:1)
我不知道这是否是最佳解决方案,但是效果很好。您应该使用“字符串”包。
library(stringr)
for (x in 1:length(keywords)) {
if (grepl("[*]", keywords[x]) == TRUE) {
keywords[x] <- substr(keywords[x],1,nchar(keywords[x])-1)
}
}
在这里,我从某些关键字中删除了“ *”符号(据我了解,您想分析它们在字符串中的部分包含情况。
重要提示:
应使用正则表达式[*]来捕获*符号。
for (x in 1:length(keywords)) {
dataframe[, keywords[x]] <- 0
}
只需使用默认值0创建新列即可。
for (x in 1:nrow(dataframe)) {
partials <- data.frame(str_split(dataframe[x,2], " "), stringsAsFactors=FALSE)
partials <- partials[partials[] != ""]
for(y in 1:length(partials)) {
for (z in 1:length(keywords)) {
if (keywords[z] == partials[y]) {
dataframe[x, keywords[z]] <- dataframe[x, keywords[z]] + 1
}
}
}
}
您将每个Tweet拆分为一个单词向量,查看关键字是否等于任何单词,如果存在则加+1,并以相同的数据帧结尾,但每个关键字都有新的列。
我用您的关键字对其进行了测试,并给出了正确的答案。
答案 1 :(得分:0)
您的要求似乎适合于矩阵类型的输出,例如,推文是行,每一项是列,单元格值为出现的次数。这是使用gsub
的基本R解决方案:
terms <- c("cat", "hat", "bat")
tweets <- c("The cat in a hat met the man with the hat and a bat",
"That cat was a fast cat!",
"I bought a baseball bat while wearing a hat")
output <- sapply(terms, function(x) {
sapply(tweets, function(y) {
(nchar(y) - nchar(gsub(paste0("\\b", x, "\\b"), "", y))) / nchar(x)
})
})
cat hat bat
The cat in a hat met the man with the hat and a bat 1 2 1
That cat was a fast cat! 2 0 0
I bought a baseball bat while wearing a hat 0 1 1
此方法首先使用terms
迭代sapply
中的每个关键字,然后迭代每个tweet。对于每个关键字/推文组合,它都会计算出现的次数。我使用的技巧是比较原始推文的长度与相同推文的长度,并删除所有出现的关键字,然后通过特定关键字的长度对差异进行归一化。
编辑:
如果您希望每个推文都包含关键字总和,那么我们可以在上述矩阵上调用rowSums
:
rowSums(output)
The cat in a hat met the man with the hat and a bat
4
That cat was a fast cat!
2
I bought a baseball bat while wearing a hat
2