R:在用户定义的函数中使用 get 和 data.table

Posted

技术标签:

【中文标题】R:在用户定义的函数中使用 get 和 data.table【英文标题】:R: Using get and data.table within a user defined function 【发布时间】:2017-08-31 13:25:15 【问题描述】:

我正在学习如何在 R 中编写使用常见包(如 data.table 和 dplyr)的函数。

我编写的这个函数计算特定类别中观察值的百分比,在其他组中(例如:2015 年发布的 10-20mpg 的汽车的份额)并生成一个表格。这里它周围没有任何功能:

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 用户功能的其他帖子(例如Get a user-defined function work in data.table)但他们似乎没有触及这个问题/遇到它。

我是新来的,所以如果有任何其他反馈/cmets 可以更好地做到这一点,我将不胜感激。

【问题讨论】:

仅供参考,.(N = .N).N 会做同样的事情,因为这是默认名称。另外,在函数中,我猜 keyby 和 by 没有任何收获。 【参考方案1】:

您不必在dt 上调用get(根据我的经验,get 最常用于使用字符串引用列),您可以将字符向量提供给by 或@ 987654325@:

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%

这里也是使用xtabsprop.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%

【讨论】:

【参考方案2】:

我愿意……

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 和 col 变量:

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)

【讨论】:

以上是关于R:在用户定义的函数中使用 get 和 data.table的主要内容,如果未能解决你的问题,请参考以下文章

R - 在用户定义的函数 R 中将字符串作为字符串传递

r语言createdatapartition在哪个函数中

R语言data.table导入数据实战:data.table使用自定义函数及Reduce函数实现一次性性多表连接

在用户定义的 R 函数中使用现有函数 [即 max()] 创建变量

在 R 用户定义函数中传递数据参数

如何用户在 R 中定义过滤参数?