tl,dr:我的函数似乎可以工作,但后来我把它挂了,它就不工作了。是功能还是搭接?
数据
我有一个数据表,其中包含已经标记为字符向量的文本:
id text
1: 1 c("sadness", "joy")
2: 2 c("anger", "scream")
3: 3 c("relief", "sadness")
我想用一本包含单词和相关情感值的词典来注释我的带有情感值的标记文本:
words emotion1 emotion2
1: sadness 1 5
2: anger 2 6
3: relief 3 7
最终目标
我希望我的search_function输出类似于以下内容的内容:
my_emotion_function(c("relief", "sadness"), lexicon_emotions)
emotion1 emotion2
1: 2 6
my_emotion_function(c("relief", "meh"), lexicon_emotions)
emotion1 emotion2
1: 3 7
my_emotion_function(c("meh", "ugh"), lexicon_emotions)
emotion1 emotion2
1: NA NA
将此应用于令牌,我将添加新列并用结果填充它们。
id text emotion1 emotion2
1: 1 c("sadness", "joy") 1 5
2: 2 c("anger", "scream") 2 6
3: 3 c("relief", "sadness") 2 6
一半起作用的功能
该函数采用一个字符向量,为匹配单词的(键控的(情感词典子集,并计算每个情感维度的平均分数。
my_emotion_function <- function(characters, lexicon){
return(lexicon[.(characters), lapply(.SD, mean, na.rm = TRUE), .SDcols = 2:3])
}
我不明白的地方
我感到困惑和不明白的是,为什么这个函数在一个字符向量上测试时似乎工作得很好(上面的例子,只在一个向量上测试,效果很好(,但当我想把它应用到data.table时,它却不起作用
我不确定这个函数是在某个方面出错,还是我把它交给了data.table。我不明白为什么单个实例可以工作,但在data.table 上不能重复
如果我执行上面的代码;文本";行,那么我只会得到每个单元格的N.A,不管单词是什么。
id text emotion1 emotion2
1: 1 c("sadness", "joy") NaN NaN
2: 2 c("anger", "scream") NaN NaN
3: 3 c("relief", "sadness") NaN NaN
如果用不相等数量的标记(比如第一行(进行测试,那么每一行都包含第一行的值。
id text emotion1 emotion2
1: 1 sadness 1 5
2: 2 c("anger", "scream") 1 5
3: 3 c("relief", "sadness") 1 5
我找不到为什么我要么得到同样的结果,要么到处都是NA。
完整的复制代码
library(data.table)
table_of_tokens <- data.table("id" = 1:3,
"text" = list(c("sadness", "joy"),
c("anger", "scream"),
c("relief", "sadness")))
table_of_tokens[, "text" := as.character(text)]
#convert to character vector to use key-subsetting in data.table
lexicon_emotions <-
data.table(
"words" = c("sadness", "anger", "relief"),
"emotion1" = 1:3,
"emotion2" = 5:7
)
setkey(lexicon_emotions, words)
my_emotion_function <- function(characters, lexicon) {
return(lexicon[.(characters),
lapply(.SD, mean, na.rm = TRUE), .SDcols = 2:3])
}
table_of_tokens[, c("emotion1", "emotion2") :=
my_emotion_function(text, lexicon_emotions)]
来源:这基本上是对syuzhet R包的重写,它依赖于data.frames,因此在我的情况下,对于大型数据集来说不够灵活或高效
编辑:这应该得到你想要的。
library(data.table)
table_of_tokens <- data.table(
"id" = 1:3,
"text" = list(
c("sadness"),
c("anger", "scream"),
c("relief", "grief"),
c("relief", "grief", "sadness")
)
)
lexicon_emotions <- data.table("words" = c("sadness", "anger", "relief"),
"emotion1" = 1:3,
"emotion2" = 5:7,
key = "words")
emotions <- names(lexicon_emotions)[-1]
table_of_tokens[,
(emotions) := {
res <- lapply(text, function(x) {
lexicon_emotions[words %chin% x,
lapply(.SD, mean, na.rm = TRUE),
.SDcols = emotions]
})
rbindlist(res)
}
]
print(table_of_tokens)
> print(table_of_tokens)
id text emotion1 emotion2
1: 1 sadness 1 5
2: 2 anger,scream 2 6
3: 3 relief,grief 3 7
4: 1 relief,grief,sadness 2 6
代码编写最重要的方面之一是调试。让我们使用一个简单的print()
调用来了解函数调用过程中发生了什么:
my_emotion_function <- function(characters, lexicon) {
print(characters) ## for debugging
return(lexicon[.(characters),
lapply(.SD, mean, na.rm = TRUE), .SDcols = 2:3])
}
table_of_tokens[, c("emotion1", "emotion2") :=
my_emotion_function(text, lexicon_emotions)]
## [1] "c("sadness", "joy")" "c("anger", "scream")" "c("relief", "sadness")"
这意味着我们实际上正在执行:
lexicon["c("sadness", "joy")" ...]
## what we actually want for each token
lexicon[c("sadness", "joy"), lapply(.SD, mean, na.rm = TRUE), .SDcols = 2:3])
要做到这一点,我们做而不是希望按照@IanCampbell的建议从列表转换为字符。另一项是,我们希望循环遍历每个元素,这意味着lapply()
可以是我们的朋友:
table_of_tokens[, c("emotion1", "emotion2") :=
rbindlist(lapply(text, my_emotion_function, lexicon_emotions))]
table_of_tokens
## id text emotion1 emotion2
## 1: 1 sadness,joy 1 5
## 2: 2 anger,scream 2 6
## 3: 3 relief,sadness 2 6
我仍然不确定如果没有比赛会发生什么。