gpt4 book ai didi

r - 学习用 R 编写函数

转载 作者:行者123 更新时间:2023-12-05 08:57:30 26 4
gpt4 key购买 nike

我正处于使用 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

我想对此进行概括,以便我可以以某种方式放入一个数据框(并且可能选择我需要排序的列,因为它有时会发生变化),然后得到扩展版本。我的第一个实现包含一个参数太多的函数(数据框,然后是我想要排序/扩展的所有列名。网格)而且它也不起作用:

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

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

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

最佳答案

乍一看,您能做的最重要的事情就是在您的函数中使用非标准求值快捷方式:比如$subset ()with()。这些函数旨在方便交互使用,而不是可扩展的编程用途。 (参见,例如,?subset 中的 Warning 应该添加到 ?with, fortunes::fortune(312) , fortunes::fortune(343).)

fortunes::fortune(312)

The problem here is that the $ notation is a magical shortcut and like any other magic if used incorrectly is likely to do the programmatic equivalent of turning yourself into a toad. -- Greg Snow (in response to a user that wanted to access a column whose name is stored in y via x$y rather than x[[y]]) R-help (February 2012)

fortunes::fortune(343)

Sooner or later most R beginners are bitten by this all too convenient shortcut. As an R newbie, think of R as your bank account: overuse of $-extraction can lead to undesirable consequences. It's best to acquire the [[ and [ habit early. -- Peter Ehlers (about the use of $-extraction) R-help (March 2013)

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

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]
}

这些产量:

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

第一个函数是错误的,因为 $ 不会评估它后面的内容,无论我在调用函数时将 col 设置为什么值, df$col 将查找字面上名为 "col" 的列。但是,括号将计算 col 并看到“哦,嘿,col 设置为 "mpg",让我们寻找其中的一列名字。”

如果您想对这个问题有更多的了解,我推荐 Non-Standard Evaluation Section of Hadley Wickham's Advanced R book .

我不会重新编写和调试您的函数,但如果我想这样做,我的第一步是删除所有 $with()、和 subset(),替换为 [。很有可能这就是您需要做的所有事情。

关于r - 学习用 R 编写函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31060416/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com