学习在R中编写函数

HFB*_*ing 2 r function

我正处于R的地步,我想开始编写自己的函数,因为我倾向于需要一遍又一遍地做同样的事情.但是,我很难看到如何概括我写的东西.查看源代码并没有帮助我很好地学习,因为通常看起来.Internal或.Primitive函数(或其他我不知道的命令)被广泛使用.我想首先将我的普通复制粘贴解决方案转换为函数 - 更好的事情可以在以后发生!

作为一个例子:我做了很多数据格式化,需要做一些操作,然后用零填充数据框,用于没有任何数据的所有其他组合(例如,没有观察的年份,因此不是最初的记录等).我需要一遍又一遍地为具有不同变量集的不同数据集执行此操作,但是这个想法和实现始终是相同的.

我解决这个问题的非功能方法是(对于特定的实现和最小的例子):

df <- data.frame(County = c(1, 45, 57),
                 Year = c(2002, 2003, 2003),
                 Level = c("Mean", "Mean", "Mean"),
                 Obs = c(1.4, 1.9, 10.2))

#Create expanded version of data frame
Counties <- seq(from = 1, to = 77, by = 2)
Years <- seq(from = 1999, to = 2014, by = 1)
Levels <- c("Max", "Mean")
Expansion <- expand.grid(Counties, Years, Levels)
Expansion[4] <- 0
colnames(Expansion) <- colnames(df)

#Merge and order them so that the observed value is on top
df_full <- merge(Expansion, df, all = TRUE)
df_full$duplicate <- with(df_full,
                          paste(Year, County, Level))

df_full <- df_full[order(df_full$Year,
                         df_full$County,
                         df_full$Level,
                         -abs(df_full$Obs)), ]

#Deduplicate by taking the first that shows up (the observation)
df_full <- df_full[ !duplicated(df_full$duplicate), ]
df_full$duplicate <- NULL
Run Code Online (Sandbox Code Playgroud)

我想概括这一点,以便我可以以某种方式放入一个数据框(并且可能选择我需要订购的列,因为有时会改变)然后获得扩展版本.我的第一个实现包含一个参数太多的函数(数据框架,然后是我想订购的所有列名称/ expand.grid),它也没有用:

gridExpand <- function(df, col1, col2=NULL, col3=NULL, measure){
  #Started with "Expansion" being a global outside of the function 
  #It is identical the first part of the above code
  ex <- merge(Expansion, df, all = TRUE)
  ex$dupe <- with(ex,
                 paste(col1, col2, col3))
   ex <- ex[order(with(ex,
                       col1, col2, col3, -abs(measure)))]
   ex <- ex[ !duplicated(ex$dupe)]
   ex <- subset(ex, select = -(dupe))  
}

df_full <- gridExpand(df, Year, County, Level, Obs)

Error in paste(col1, col2, col3) : object 'Year' not found
Run Code Online (Sandbox Code Playgroud)

我假设这不起作用,因为R无法知道从哪里来'Year'.我可能会尝试, paste(df, "$Year")但它会创建"df$Year"明显不起作用.而且我从来没有看到其他人在他们的功能中这么做,所以我很想念人们在数据框相关功能中引用的东西.

理想情况下,我想了解一些有助于思考概括的资源,或者如果有人可以指出我正确的方向来解决这个特定的问题,我认为这可能会帮助我看到我做错了什么.我不知道有更好的方式寻求帮助 - 我一直在尝试阅读有关编写函数的教程大约3个月而且没有点击.

Gre*_*gor 6

一目了然,你可以做最重要的事情是使用你的内部函数非标准评估快捷键:之类的东西$,subset()with().这些功能旨在方便交互式使用,而不是可扩展的程序化使用.(参见,例如,警告,?subset其中可能应添加到?with,, fortunes::fortune(312))fortunes::fortune(343).

fortunes::fortune(312)
Run Code Online (Sandbox Code Playgroud)

这里的问题是$符号是一个神奇的快捷方式,如果使用不正确的任何其他魔法可能会做程序相当于把自己变成一个蟾蜍.- Greg Snow(响应想要访问名称存储在yvia x$y而非x[[y]]R-help 的列的用户)(2012年2月)

fortunes::fortune(343)
Run Code Online (Sandbox Code Playgroud)

迟早大多数R初学者都会被这​​个太方便的快捷方式所困扰.作为R新手,将R视为您的银行账户:过度使用$ -extraction会导致不良后果.这是最好的获取[[[习惯早. - Peter Ehlers(关于使用$ -extraction)R-help(2013年3月)

当您开始编写处理数据框的函数时,如果需要引用列名,则应将它们作为字符串传递,然后使用[[[根据存储在变量名中的字符串获取列.这是使用户指定的列名称使函数灵活的最简单方法.例如,这是一个简单的愚蠢函数,用于测试数据框是否具有给定名称的列:

does_col_exist_1 = function(df, col) {
    return(!is.null(df$col))
}

does_col_exist_2 = function(df, col) {
    return(!is.null(df[[col]])
    # equivalent to df[, col]
}
Run Code Online (Sandbox Code Playgroud)

这些产量:

does_col_exist_1(mtcars, col = "jhfa")
# [1] FALSE
does_col_exist_1(mtcars, col = "mpg")
# [1] FALSE

does_col_exist_2(mtcars, col = "jhfa")
# [1] FALSE
does_col_exist_2(mtcars, col = "mpg")
# [1] TRUE
Run Code Online (Sandbox Code Playgroud)

第一个函数是错误的,因为$不评估它后面的内容,无论我col在调用函数时设置的值是什么,df$col都会查找一个字面命名的列"col".然而,括号将评估col并看到"哦,嘿,col设置为"mpg",让我们查找该名称的列."

如果你想更多地了解这个问题,我会推荐Hadley Wickham的高级R书非标准评估部分.

我不打算重新编写和调试的功能,但如果我想我的第一个步骤是清除所有$,with()以及subset()与更换[.这是一个非常好的机会,你需要做的就是.

  • 我希望我能接受这两次 - 一次是为了向我提供我需要的帮助,再次向我介绍财富包...... (2认同)