我们假设以下是我的数据表data
data <- setDT(structure(list(col1 = c(1, 2, 3, 4, 5), col2 = c(53, 45, 54,
97, 23), col3 = c("aa aa aa aa ab ad af ae ar", "bb bb bb bb bt by bu bi bo",
"cc cc cc cc cd cy ch cn cd", "dd dd dd dd dt dy dj dk da", "ee ee ee ee et eh es er eg"
), col4 = c("aa bb ff ff","aa ff vv rr","dd dd rr gg",
"yy yy rr rr","uu uu uu ee")), .Names = c("col1", "col2", "col3", "col4"),
row.names = c(NA, -5L), class = "data.frame"))
col1 col2 col3 col4
1 53 aa aa aa aa ab ad af ae ar aa bb ff ff
2 45 bb bb bb bb bt by bu bi bo aa ff vv rr
3 54 cc cc cc cc cd cy ch cn cd dd dd rr gg
4 97 dd dd dd dd dt dy dj dk da yy yy rr rr
5 23 ee ee ee ee et eh es er eg uu uu uu ee
col3
包含一系列字词,我需要找到,如果col3中出现频率最高的word
出现在col4
中。因此输出如下所示:
col1 col2 col3 col4 most_freq_word_in_cool3 out_col
1 53 aa aa aa aa ab ad af ae ar aa bb ff ff aa 1
2 45 bb bb bb bb bt by bu bi bo aa ff vv rr bb 0
3 54 cc cc cc cc cd cy ch cn cd dd dd rr gg cc 0
4 97 dd dd dd dd dt dy dj dk da yy yy rr rr dd 0
5 23 ee ee ee ee et eh es er eg uu uu uu ee ee 1
我尝试了以下解决方案
m_fre_word1 <- function(x) { string <- as.character(unlist(strsplit(x, " ")))
freq <- sort(table(string), decreasing = T)
wr <-names(freq)[1]
return(wr) }
data <- data[ , most_freq_word_in_cool3:= apply(data[ , .(col3)], 1, m_fre_word1)]
data <- data[ , out_col:= as.numeric(grepl(m_fre_word1(col3), col4))]
这个解决方案没有任何问题,但它确实很慢。我的数据表很大。我无法使用这种方式,因此我正在寻找更快的替代方案。有人可以建议更快的替代方案。
谢谢,
答案 0 :(得分:2)
这是一次尝试。我建议拆分列并以长格式操作,而不是在每一行上运行整个事情。
我从here窃取Mode
函数,其定义如下
Mode <- function(x) {
ux <- unique(x)
ux[which.max(tabulate(match(x, ux)))]
}
现在使用我们可以做的最新data.table
版本
library(data.table) # v 1.9.6+
temp <- setDT(data6)[, tstrsplit(col3, " ", fixed = TRUE)]
data6[, res := melt(temp[, indx := .I], id = "indx")[, Mode(value), by = indx]$V1]
data6
# col1 col2 col3 col4 res
# 1: 1 53 aa aa aa aa ab ad af ae ar aa bb ff ff aa
# 2: 2 45 bb bb bb bb bt by bu bi bo aa ff vv rr bb
# 3: 3 54 cc cc cc cc cd cy ch cn cd dd dd rr gg cc
# 4: 4 97 dd dd dd dd dt dy dj dk da yy yy rr rr dd
# 5: 5 23 ee ee ee ee et eh es er eg uu uu uu ee ee
第二步可以通过eitehr轻松实现
data6[, out := +grepl(res, col4, fixed = TRUE), by = res]
或(不确定哪一个更快)
library(stringi)
data6[stri_detect_fixed(col4, res), out := 1L]
作为旁注,当使用引用语义时,不需要复制整个数据集并使用<-
重新分配它,实际上这是整个引用语义点。请阅读this。
答案 1 :(得分:2)
我认为apply(data[ , .(col3)]
会降低您的代码速度。通常我发现在data.table调用中放置一个子集会导致巨大的减速,因为子集操作很昂贵。
您可以尝试:
DT[ , test := names(sort(table(strsplit(col3," ")), decreasing = T))[1], by = col1]
DT[, search := gsub(" ","|",col4)]
DT[, output := grepl(search,test), by = col1]
不确定我或大卫的回答是否会更快。
编辑:根据Frank的输入,最后两行可以替换为:
DT[, output := mapply(grepl,gsub(" ","|",col4),test)]
答案 2 :(得分:1)
(根据以下评论编辑)
加载库
require(data.table)
定义数据
x <-
data.table(
col1 = c(1, 2, 3, 4, 5),
col2 = c(53, 45, 54, 97, 23),
col3 = c(
"aa aa aa aa ab ad af ae ar", "bb bb bb bb bt by bu bi bo",
"cc cc cc cc cd cy ch cn cd", "dd dd dd dd dt dy dj dk da",
"ee ee ee ee et eh es er eg"),
col4 = c(
"aa bb ff ff","aa ff vv rr","dd dd rr gg",
"yy yy rr rr","uu uu uu ee")
)
找到col3中最常见的元素
x[,most_freq_word_in_col3:=sapply(col3,function(e){
names(sort(table(unlist(strsplit(e," "))),decreasing=TRUE)[1])})]
检查col4中的这个元素是否
x[,out_col:=apply(cbind(most_freq_word_in_col3,col4),1,function(e){
as.numeric(e[1] %in% unlist(strsplit(e[2]," ")))})]
输出:
> x
col1 col2 col3 col4 most_freq_word_in_col3 out_col
1: 1 53 aa aa aa aa ab ad af ae ar aa bb ff ff aa 1
2: 2 45 bb bb bb bb bt by bu bi bo aa ff vv rr bb 0
3: 3 54 cc cc cc cc cd cy ch cn cd dd dd rr gg cc 0
4: 4 97 dd dd dd dd dt dy dj dk da yy yy rr rr dd 0
5: 5 23 ee ee ee ee et eh es er eg uu uu uu ee ee 1