R data.table 列名在函数中不起作用
R data.table column names not working within a function
我想在一个函数中使用 data.table,我想了解我的代码失败的原因。我有一个 data.table 如下:
DT <- data.table(my_name=c("A","B","C","D","E","F"),my_id=c(2,2,3,3,4,4))
> DT
my_name my_id
1: A 2
2: B 2
3: C 3
4: D 3
5: E 4
6: F 4
我正在尝试创建具有不同 "my_id" 值的所有 "my_name" 对,对于 DT 来说是:
Var1 Var2
A C
A D
A E
A F
B C
B D
B E
B F
C E
C F
D E
D F
我有一个函数 return 所有 "my_name" 对给定的 "my_id" 值对,这按预期工作。
get_pairs <- function(id1,id2,tdt) {
return(expand.grid(tdt[my_id==id1,my_name],tdt[my_id==id2,my_name]))
}
> get_pairs(2,3,DT)
Var1 Var2
1 A C
2 B C
3 A D
4 B D
现在,我想对所有 ID 对执行此函数,我尝试通过查找所有 ID 对然后将 mapply 与 get_pairs 函数一起使用来实现。
> combn(unique(DT$my_id),2)
[,1] [,2] [,3]
[1,] 2 2 3
[2,] 3 4 4
tid1 <- combn(unique(DT$my_id),2)[1,]
tid2 <- combn(unique(DT$my_id),2)[2,]
mapply(get_pairs, tid1, tid2, DT)
Error in expand.grid(tdt[my_id == id1, my_name], tdt[my_id == id2, my_name]) :
object 'my_id' not found
同样,如果我尝试在没有 mapply 的情况下做同样的事情,它会起作用。
get_pairs3(tid1[1],tid2[1],DT)
Var1 Var2
1 A C
2 B C
3 A D
4 B D
为什么这个函数只有在mapply 中使用时才会失败?我认为这与 data.table 名称的范围有关,但我不确定。
或者,是否有 different/more 有效的方法来完成此任务?我有一个很大的 data.table 和第三个 id "sample" 我需要为每个样本获取所有这些对(例如在 DT[sample=="sample_id",] 上操作)。我是 data.table 包的新手,我可能没有以最有效的方式使用它。
枚举所有可能的对
u_name <- unique(DT$my_name)
all_pairs <- CJ(u_name,u_name)[V1 < V2]
枚举观察到的对
obs_pairs <- unique(
DT[,{un <- unique(my_name); CJ(un,un)[V1 < V2]}, by=my_id][, !"my_id"]
)
取差值
all_pairs[!J(obs_pairs)]
CJ
与 expand.grid
类似,只是它创建了一个 data.table 并将其所有列作为其键。 A data.table X
必须被键控才能使连接 X[J(Y)]
或非连接 X[!J(Y)]
(如最后一行)起作用。 J
是可选的,但可以更明显地表明我们正在进行连接。
简化。 @CathG 指出,如果每个 [=36] 总是有两个排序的 "names",那么有一种更简洁的构造 obs_pairs
的方法=](如示例数据中所示):使用 as.list(un)
代替 CJ(un,un)[V1 < V2]
.
Why does this function fail only when used within an mapply? I think
this has something to do with the scope of data.table names, but I'm
not sure.
在这种情况下,函数失败的原因与范围界定无关。 mapply
向量化函数,它获取每个参数的每个元素并传递给函数。因此,在您的情况下,data.table
元素是它的列,因此 mapply
正在传递列 my_name
而不是完整的 data.table
.
如果要将完整的 data.table
传递给 mapply
,则应使用 MoreArgs
参数。然后你的功能将起作用:
res <- mapply(get_pairs, tid1, tid2, MoreArgs = list(tdt=DT), SIMPLIFY = FALSE)
do.call("rbind", res)
Var1 Var2
1 A C
2 B C
3 A D
4 B D
5 A E
6 B E
7 A F
8 B F
9 C E
10 D E
11 C F
12 D F
函数 debugonce()
在这些情况下非常有用。
debugonce(mapply)
mapply(get_pairs, tid1, tid2, DT)
# Hit enter twice
# from within BROWSER
debugonce(FUN)
# Hit enter twice
# you'll be inside your function, and then type DT
DT
# [1] "A" "B" "C" "D" "E" "F"
Q # (to quit debugging mode)
这是错误的。基本上,mapply()
获取每个输入参数的第一个元素并将其传递给您的函数。在本例中,您提供了 data.table,它也是 list。因此,它不是传递整个 data.table,而是传递列表(列)的每个元素。
因此,您可以通过以下方式解决此问题:
mapply(get_pairs, tid1, tid2, list(DT))
但是 mapply()
默认情况下会简化结果,因此您会得到 matrix
返回。你必须使用 SIMPLIFY = FALSE
.
mapply(get_pairs, tid1, tid2, list(DT), SIMPLIFY = FALSE)
或者直接使用Map
:
Map(get_pairs, tid1, tid2, list(DT))
使用rbindlist()
绑定结果。
HTH
我想在一个函数中使用 data.table,我想了解我的代码失败的原因。我有一个 data.table 如下:
DT <- data.table(my_name=c("A","B","C","D","E","F"),my_id=c(2,2,3,3,4,4))
> DT
my_name my_id
1: A 2
2: B 2
3: C 3
4: D 3
5: E 4
6: F 4
我正在尝试创建具有不同 "my_id" 值的所有 "my_name" 对,对于 DT 来说是:
Var1 Var2
A C
A D
A E
A F
B C
B D
B E
B F
C E
C F
D E
D F
我有一个函数 return 所有 "my_name" 对给定的 "my_id" 值对,这按预期工作。
get_pairs <- function(id1,id2,tdt) {
return(expand.grid(tdt[my_id==id1,my_name],tdt[my_id==id2,my_name]))
}
> get_pairs(2,3,DT)
Var1 Var2
1 A C
2 B C
3 A D
4 B D
现在,我想对所有 ID 对执行此函数,我尝试通过查找所有 ID 对然后将 mapply 与 get_pairs 函数一起使用来实现。
> combn(unique(DT$my_id),2)
[,1] [,2] [,3]
[1,] 2 2 3
[2,] 3 4 4
tid1 <- combn(unique(DT$my_id),2)[1,]
tid2 <- combn(unique(DT$my_id),2)[2,]
mapply(get_pairs, tid1, tid2, DT)
Error in expand.grid(tdt[my_id == id1, my_name], tdt[my_id == id2, my_name]) :
object 'my_id' not found
同样,如果我尝试在没有 mapply 的情况下做同样的事情,它会起作用。
get_pairs3(tid1[1],tid2[1],DT)
Var1 Var2
1 A C
2 B C
3 A D
4 B D
为什么这个函数只有在mapply 中使用时才会失败?我认为这与 data.table 名称的范围有关,但我不确定。
或者,是否有 different/more 有效的方法来完成此任务?我有一个很大的 data.table 和第三个 id "sample" 我需要为每个样本获取所有这些对(例如在 DT[sample=="sample_id",] 上操作)。我是 data.table 包的新手,我可能没有以最有效的方式使用它。
枚举所有可能的对
u_name <- unique(DT$my_name)
all_pairs <- CJ(u_name,u_name)[V1 < V2]
枚举观察到的对
obs_pairs <- unique(
DT[,{un <- unique(my_name); CJ(un,un)[V1 < V2]}, by=my_id][, !"my_id"]
)
取差值
all_pairs[!J(obs_pairs)]
CJ
与 expand.grid
类似,只是它创建了一个 data.table 并将其所有列作为其键。 A data.table X
必须被键控才能使连接 X[J(Y)]
或非连接 X[!J(Y)]
(如最后一行)起作用。 J
是可选的,但可以更明显地表明我们正在进行连接。
简化。 @CathG 指出,如果每个 [=36] 总是有两个排序的 "names",那么有一种更简洁的构造 obs_pairs
的方法=](如示例数据中所示):使用 as.list(un)
代替 CJ(un,un)[V1 < V2]
.
Why does this function fail only when used within an mapply? I think this has something to do with the scope of data.table names, but I'm not sure.
在这种情况下,函数失败的原因与范围界定无关。 mapply
向量化函数,它获取每个参数的每个元素并传递给函数。因此,在您的情况下,data.table
元素是它的列,因此 mapply
正在传递列 my_name
而不是完整的 data.table
.
如果要将完整的 data.table
传递给 mapply
,则应使用 MoreArgs
参数。然后你的功能将起作用:
res <- mapply(get_pairs, tid1, tid2, MoreArgs = list(tdt=DT), SIMPLIFY = FALSE)
do.call("rbind", res)
Var1 Var2
1 A C
2 B C
3 A D
4 B D
5 A E
6 B E
7 A F
8 B F
9 C E
10 D E
11 C F
12 D F
函数 debugonce()
在这些情况下非常有用。
debugonce(mapply)
mapply(get_pairs, tid1, tid2, DT)
# Hit enter twice
# from within BROWSER
debugonce(FUN)
# Hit enter twice
# you'll be inside your function, and then type DT
DT
# [1] "A" "B" "C" "D" "E" "F"
Q # (to quit debugging mode)
这是错误的。基本上,mapply()
获取每个输入参数的第一个元素并将其传递给您的函数。在本例中,您提供了 data.table,它也是 list。因此,它不是传递整个 data.table,而是传递列表(列)的每个元素。
因此,您可以通过以下方式解决此问题:
mapply(get_pairs, tid1, tid2, list(DT))
但是 mapply()
默认情况下会简化结果,因此您会得到 matrix
返回。你必须使用 SIMPLIFY = FALSE
.
mapply(get_pairs, tid1, tid2, list(DT), SIMPLIFY = FALSE)
或者直接使用Map
:
Map(get_pairs, tid1, tid2, list(DT))
使用rbindlist()
绑定结果。
HTH