R:在用户定义的函数中使用 get 和 data.table
R: Using get and data.table within a user defined function
我正在学习如何使用 data.table 和 dplyr 等常用包在 R 中编写函数。
我写的这个函数计算特定类别的观察值在其他一些组中的百分比(例如:2015 年发布的 10-20mpg 汽车的份额)并生成 table .这里没有围绕它的函数:
library(data.table)
library(scales)
#Create test dataframe and cut off points
test<-data.frame(x=c(0:10), y=c(rep(1,5),rep(2,6)), z=c("A","A","A","B","B","B","C","C","C","C","C"))
test <- data.table(test)
#trial non function version (calculating share of row by category z): works
tmp<-test[,.(N=.N), keyby=.(y,z)]
tmp[,total:=sum(N), by=y]
tmp[,percent:=percent(N/total)]
dcast(tmp,y ~ z, value.var="percent")
但是为了让它在一个函数中工作,我不得不使用 get。一旦 get 被评估,两个分类变量必须被称为 "get" 和 "get.1" 用于代码的其余部分(见下文)。有没有办法避免这种情况?
#Two way table function: data.table
tw_tab<-function(dt,v1,v2){
#set up variables as charaters
v1<-as.character(substitute(v1))
v2<-as.character(substitute(v2))
dt<-as.character(substitute(dt))
#function
tmp<-get(dt)[,.(N=.N), keyby=.(get(v1),get(v2))]
tmp[,total:=sum(N), by=get]
tmp[,percent:=percent(N/total)]
dcast(tmp,get ~ get.1, value.var="percent")
}
#test function
tw_tab(test, y, z)
我尝试在整个代码中只使用 "get(v1)" 和 "get(v2)",但这不起作用
我看过其他关于 data.table 用户功能的帖子(例如 ),但他们似乎没有涉及这个 issue/encounter。
我是这方面的新手,所以如果有任何其他人 feedback/comments 有更好的方法可以做到这一点,我将不胜感激。
您不必在 dt
上调用 get
(根据我的经验,get
最常用于引用使用字符串的列)并且您可以提供字符向量到 by
或 keyby
:
tw_tab <- function(dt,v1,v2){
#set up variables as charaters
v1<-as.character(substitute(v1))
v2<-as.character(substitute(v2))
#function
tmp <- dt[,.(N=.N), keyby = c(v1, v2)]
tmp[,total:=sum(N), by= c(v1)]
tmp[,percent:=percent(N/total)]
dcast(tmp, paste(v1, '~', v2), value.var="percent")
}
#test function
tw_tab(test, y, z)
# y A B C
# 1: 1 60.0% 40.0% NA
# 2: 2 NA 16.7% 83.3%
这里还有一个使用xtabs
和prop.table
的解决方案:
tw_tab <- function(x, v1, v2){
fm <- bquote(~ .(substitute(v1)) + .(substitute(v2)))
res <- prop.table(xtabs(formula = fm, data = x), 1)
res <- as.data.frame.matrix(res)
res[] <- lapply(res, scales::percent)
return(res)
}
tw_tab(test, y, z)
# A B C
# 1 60% 40.0% 0.0%
# 2 0% 16.7% 83.3%
我愿意...
row_pct = function(DT, fm){
all = all.vars(fm)
lhs = all.vars(fm[[2]])
rhs = all.vars(fm[[3]])
DT[, .N, by=all][,
p := percent(N/sum(N)), by=lhs][,
dcast(.SD, eval(fm), value.var = "p", fill = percent(0))]
}
示例:
row_pct(test, y ~ z)
y A B C
1: 1 60% 40% 0%
2: 2 0% 16.7% 83.3%
row_pct(data.table(mtcars), cyl + gear ~ carb)
cyl gear 1 2 3 4 6 8
1: 4 3 100% 0% 0% 0% 0% 0%
2: 4 4 50% 50% 0% 0% 0% 0%
3: 4 5 0% 100% 0% 0% 0% 0%
4: 6 3 100% 0% 0% 0% 0% 0%
5: 6 4 0% 0% 0% 100% 0% 0%
6: 6 5 0% 0% 0% 0% 100% 0%
7: 8 3 0% 33.3% 25.0% 41.7% 0% 0%
8: 8 5 0% 0% 0% 50% 0% 50%
如果出于某种原因您想分别输入行和列变量:
row_pct2 = function(DT, rowvars, colvar){
fm = substitute(`~`(rowvars, colvar))
row_pct(DT, fm)
}
# Examples:
row_pct2(test, y, z)
row_pct2(data.table(mtcars), cyl + gear, carb)
我正在学习如何使用 data.table 和 dplyr 等常用包在 R 中编写函数。
我写的这个函数计算特定类别的观察值在其他一些组中的百分比(例如:2015 年发布的 10-20mpg 汽车的份额)并生成 table .这里没有围绕它的函数:
library(data.table)
library(scales)
#Create test dataframe and cut off points
test<-data.frame(x=c(0:10), y=c(rep(1,5),rep(2,6)), z=c("A","A","A","B","B","B","C","C","C","C","C"))
test <- data.table(test)
#trial non function version (calculating share of row by category z): works
tmp<-test[,.(N=.N), keyby=.(y,z)]
tmp[,total:=sum(N), by=y]
tmp[,percent:=percent(N/total)]
dcast(tmp,y ~ z, value.var="percent")
但是为了让它在一个函数中工作,我不得不使用 get。一旦 get 被评估,两个分类变量必须被称为 "get" 和 "get.1" 用于代码的其余部分(见下文)。有没有办法避免这种情况?
#Two way table function: data.table
tw_tab<-function(dt,v1,v2){
#set up variables as charaters
v1<-as.character(substitute(v1))
v2<-as.character(substitute(v2))
dt<-as.character(substitute(dt))
#function
tmp<-get(dt)[,.(N=.N), keyby=.(get(v1),get(v2))]
tmp[,total:=sum(N), by=get]
tmp[,percent:=percent(N/total)]
dcast(tmp,get ~ get.1, value.var="percent")
}
#test function
tw_tab(test, y, z)
我尝试在整个代码中只使用 "get(v1)" 和 "get(v2)",但这不起作用
我看过其他关于 data.table 用户功能的帖子(例如
我是这方面的新手,所以如果有任何其他人 feedback/comments 有更好的方法可以做到这一点,我将不胜感激。
您不必在 dt
上调用 get
(根据我的经验,get
最常用于引用使用字符串的列)并且您可以提供字符向量到 by
或 keyby
:
tw_tab <- function(dt,v1,v2){
#set up variables as charaters
v1<-as.character(substitute(v1))
v2<-as.character(substitute(v2))
#function
tmp <- dt[,.(N=.N), keyby = c(v1, v2)]
tmp[,total:=sum(N), by= c(v1)]
tmp[,percent:=percent(N/total)]
dcast(tmp, paste(v1, '~', v2), value.var="percent")
}
#test function
tw_tab(test, y, z)
# y A B C
# 1: 1 60.0% 40.0% NA
# 2: 2 NA 16.7% 83.3%
这里还有一个使用xtabs
和prop.table
的解决方案:
tw_tab <- function(x, v1, v2){
fm <- bquote(~ .(substitute(v1)) + .(substitute(v2)))
res <- prop.table(xtabs(formula = fm, data = x), 1)
res <- as.data.frame.matrix(res)
res[] <- lapply(res, scales::percent)
return(res)
}
tw_tab(test, y, z)
# A B C
# 1 60% 40.0% 0.0%
# 2 0% 16.7% 83.3%
我愿意...
row_pct = function(DT, fm){
all = all.vars(fm)
lhs = all.vars(fm[[2]])
rhs = all.vars(fm[[3]])
DT[, .N, by=all][,
p := percent(N/sum(N)), by=lhs][,
dcast(.SD, eval(fm), value.var = "p", fill = percent(0))]
}
示例:
row_pct(test, y ~ z)
y A B C
1: 1 60% 40% 0%
2: 2 0% 16.7% 83.3%
row_pct(data.table(mtcars), cyl + gear ~ carb)
cyl gear 1 2 3 4 6 8
1: 4 3 100% 0% 0% 0% 0% 0%
2: 4 4 50% 50% 0% 0% 0% 0%
3: 4 5 0% 100% 0% 0% 0% 0%
4: 6 3 100% 0% 0% 0% 0% 0%
5: 6 4 0% 0% 0% 100% 0% 0%
6: 6 5 0% 0% 0% 0% 100% 0%
7: 8 3 0% 33.3% 25.0% 41.7% 0% 0%
8: 8 5 0% 0% 0% 50% 0% 50%
如果出于某种原因您想分别输入行和列变量:
row_pct2 = function(DT, rowvars, colvar){
fm = substitute(`~`(rowvars, colvar))
row_pct(DT, fm)
}
# Examples:
row_pct2(test, y, z)
row_pct2(data.table(mtcars), cyl + gear, carb)