R 以编程方式指定数据表中函数内的列名

R 以编程方式指定数据表中函数内的列名,r,data.table,n-gram,corpus,R,Data.table,N Gram,Corpus,这是我前几天问的(我现在认为我应该同时问这个问题) 资料 token.dt是一个由数据表组成的列表,每个数据表对应于n克中的n,包括n克(即n个单词序列)及其分数 > head(token.dt[[2]]) V1 V2 mi2 1: 0 0 6.494179 2: 0 001 13.249067 3: 0 002 13.249067 4: 0 005 13.249067 5: 0 025 13.249067 6: 0 039 13.249067 &g

这是我前几天问的(我现在认为我应该同时问这个问题)

资料
token.dt
是一个由数据表组成的列表,每个数据表对应于n克中的n,包括n克(即n个单词序列)及其分数

> head(token.dt[[2]])
   V1  V2       mi2
1:  0   0  6.494179
2:  0 001 13.249067
3:  0 002 13.249067
4:  0 005 13.249067
5:  0 025 13.249067
6:  0 039 13.249067

> head(token.dt[[5]])
   V1  V2 V3       V4    V5       mi5
1:  0   0  1        0     1 10.353265
2:  0 001 in    apart   for  6.807743
3:  0 001 in    thick   and  5.190449
4:  0 002 on     each  side 11.688710
5:  0 005  m       in     f  9.940322
6:  0 025 in aluminum which  8.249075
任务 任务是选择满足以下条件的n-gram(即
token.dt
中的表行)。只有当n-gram的分数高于通过以下方式确定的n-1 gram和n+1 gram的分数时,算法才会保留n-gram:

  • 与n-gram的前n-1个单词匹配的n-1个gram和
  • 前n个单词与n-gram匹配的n+1个gram

例如,考虑以下内容:

> for (i in 2:n) setkeyv(token.dt[[i]], paste0("V", 1:i))
> token.dt[[2]][J("0", "1")]
   V1 V2      mi2
1:  0  1 7.135725

> token.dt[[3]][J("0", "1")]
   V1 V2        V3       mi3
1:  0  1         0  9.803035
2:  0  1         2  6.809646
3:  0  1         f  6.142258
4:  0  1         m  7.315181
5:  0  1 milligram 13.517241
6:  0  1        mv 13.517241
7:  0  1        of  1.151899
8:  0  1       the  0.214648
9:  0  1        to  3.633922

> token.dt[[4]][J("0", "1")]
    V1 V2        V3      V4       mi4
 1:  0  1         0       1 10.507784
 2:  0  1         2       3 11.541023
 3:  0  1         f     the  3.927859
 4:  0  1         m neutral 13.621798
 5:  0  1 milligram      of  3.852570
 6:  0  1 milligram     per 10.638304
 7:  0  1        mv       m 11.260860
 8:  0  1        of  making 12.235372
 9:  0  1       the  number  9.707556
10:  0  1        to       0 12.669723
11:  0  1        to       5 11.158356
这里,三元图(三个单词的序列)0 1 0不被保留,因为尽管共享前两个单词(0 1)的二元图的分数较低(9.803035>7.135725),但前三个单词与三元图(0 1 0 1)匹配的四元图的分数高于所关注的三元图(10.507784>9.803035)

保留0.1毫克的三角形是因为其分数高于共享前两个单词(13.517241>7.135725)的二元数和前三个单词与三角形匹配的两个4克数(13.517241>3.852570,13.517241>10.638304)

上述任务通过以下方式以非编程方式实现

> z <- token.dt[[4]][token.dt[[3]][token.dt[[2]], allow.cartesian = TRUE], list(k = all(mi3 > max(mi2, mi4)), mi3), allow.cartesian = TRUE][(k)]
> head(z)
   V1 V2        V3    k      mi3
1:  0  1 milligram TRUE 13.51724
2:  0  1        mv TRUE 13.51724
3:  0 15         g TRUE 12.24260
4:  0  2      gram TRUE 13.52079
5:  0  2     mrads TRUE 13.34449
6:  0  3        wt TRUE 13.28771
试图当场计算上面的字符串会导致找不到列。将
envir=.SD
添加到下面的
eval
s会导致与下面相同的错误

> z <- token.dt[[i + 1]][token.dt[[i]][token.dt[[i - 1]], allow.cartesian = TRUE], list(k = all(eval(parse(text = paste0("mi", i))) > max(eval(parse(text = paste0("mi", i - 1))), eval(parse(text = paste0("mi", i + 1))))), eval(parse(text = paste0("mi", i)))), allow.cartesian = TRUE][(k)]
Error in eval(expr, envir, enclos) : object 'mi3' not found
>z max(eval(解析(text=paste0(“mi”,i-1)))、eval(解析(text=paste0(“mi”,i+1俬))、eval(解析(text=paste0(“mi”,i)))、allow.cartesian=TRUE][(k)]
eval(expr、envir、enclose)中出错:找不到对象“mi3”
到目前为止,唯一有效的方法是首先连接必要的数据表,然后按照上面相同的方法进行操作

> for (j in 2:4) {
+   if (j == 2) {
+     all <- copy(token.dt[[j]])
+   } else {
+     all <- token.dt[[j]][all, allow.cartesian = TRUE]
+   }
+ }

> head(all)
   V1  V2 V3       V4       mi4       mi3       mi2
1:  0   0  1        0 13.292479  9.766820  6.494179
2:  0 001 in    apart 13.233742  5.624795 13.249067
3:  0 001 in    thick 13.005608  5.624795 13.249067
4:  0 002 on     each 10.416711  7.301489 13.249067
5:  0 005  m       in  5.625874 11.205271 13.249067
6:  0 025 in aluminum 13.443647  5.624795 13.249067

> z <- all[1:1000 , list(k = all(eval(parse(text = paste0("mi", i)), envir = .SD) > max(eval(parse(text = paste0("mi", i - 1)), envir = .SD), eval(parse(text = paste0("mi", i + 1)), envir = .SD))), mi = eval(parse(text = paste0("mi", i)), envir = .SD)), by = c(paste0("V", 1:i))][(k)]
> z <- unique(z)
> head(z)
   V1 V2        V3    k       mi
1:  0  1 milligram TRUE 13.51724
2:  0  1        mv TRUE 13.51724
3:  0 15         g TRUE 12.24260
4:  0  2      gram TRUE 13.52079
5:  0  2     mrads TRUE 13.34449
6:  0  3        wt TRUE 13.28771
(2:4中的j){ +如果(j==2){ +所有z max(eval(解析(text=paste0(“mi”,i-1)),envir=.SD),eval(解析(text=paste0(“mi”,i+1)),envir=.SD)),mi=eval(解析(text=paste0(“mi”,i)),envir=.SD)),by=c(paste0(“V”,1:i))[(k)] >z头(z) V1 V2 V3千英里 1:01毫克真值13.51724 2:01毫伏真值13.51724 3:0 15克真12.24260 4:02克真值13.52079 5:0 2 mrads真实值13.34449 6:03重量真实值13.28771 然而,这是不可接受的缓慢。处理970696行中的1000行(以上)需要5秒钟以上。鉴于我在这里使用的语料库比我想要应用算法的语料库小得多,我正在寻找加快处理速度的方法

可复制示例 下面的模拟数据集应该能够说明这一点

token.dt <- list()
types <- combn(LETTERS, 3, paste, collapse = "")
set.seed(1)
data <- data.table(matrix(sample(types, 4 * 1E6, replace = TRUE), ncol = 4))
setkey(data, V1, V2, V3, V4)
set.seed(1)
for (n in 2:4) {
    token.dt[[n]] <- unique(cbind(data[ , 1:n, with = FALSE]))
    token.dt[[n]][ , paste0("mi", n) := runif(nrow(token.dt[[n]])) * 10]
}

token.dt为了使
eval
方法起作用,您必须首先构建整个表达式,然后构建
eval
。我在示例的简化版本上运行了此操作(40个值而不是4e6):


我想你可能想把重点放在你重复的例子上,把你实际问题的其余部分放在一个要点上。谢谢你的建议。我刚刚把它减少到了一定程度,虽然它仍然有点长。我在发布之前试着缩短它,但不太确定如何缩短。可能会尝试使用bquote使它更具可读性;j这是一个建议。@ClaytonStanley,虽然我没有想到这一点(一开始是,哦,Duh!),但问题的本质是,我认为你必须求助于这样的东西:
bquote((as.name(paste0(“m”,I)))>。.name(paste0(“m”,I+1))
,我不确定是否更清楚。如果你有更好的方法,请告诉我。
token.dt <- list()
types <- combn(LETTERS, 3, paste, collapse = "")
set.seed(1)
data <- data.table(matrix(sample(types, 4 * 1E6, replace = TRUE), ncol = 4))
setkey(data, V1, V2, V3, V4)
set.seed(1)
for (n in 2:4) {
    token.dt[[n]] <- unique(cbind(data[ , 1:n, with = FALSE]))
    token.dt[[n]][ , paste0("mi", n) := runif(nrow(token.dt[[n]])) * 10]
}
i <- 3
x <- parse(
  text=paste0(
    "list(k = all(mi", i, " > max(mi", i - 1, 
    ", mi", i + 1, ")), mi", i, ")"
) )  
token.dt[[i + 1]][
  token.dt[[i]][token.dt[[i - 1]], allow.cartesian = TRUE], 
  eval(x),
  allow.cartesian = TRUE
][(k)]
#     V1  V2  V3    k      mi3
# 1: CIX BQV OWY TRUE 6.870228
# 2: GIU IJM HMO TRUE 7.698414
# 3: NQR FHN DOY TRUE 9.919061
# 4: PSX IPQ ACN TRUE 7.774452