我必须承认,在试图理解函数中的函数是如何在R中定义和传递时,我必须承认完全的疯狂。这些例子总是假定您理解每一个细微之处,而不提供对过程的描述。我还没有遇到一个通俗易懂的,白痴导游的过程。所以第一个问题是你知道其中一个吗?
现在我的身体问题。
我有一个data.frames列表: fileData。
我希望在每个data.frame中的特定列上使用rollapply()函数。然后我想要所有的结果(列表)的总和。因此,从其中一个data.frames开始,使用内置的mtcar数据格式作为示例:
当然,我需要告诉rollapply()使用函数PPI()以及相关的参数,这些参数是列。
PPI <- function(a, b){
value = (a + b)
PPI = sum(value)
return(PPI)
}我试过这个:
f <- function(x) PPI(x$mpg, x$disp)
fileData<- list(mtcars, mtcars, mtcars)
df <- fileData[[1]]然后被拦在
rollapply(df, 20, f)
Error in x$mpg : $ operator is invalid for atomic vectors 我认为这与Zoo使用矩阵有关,但其他许多尝试都无法解决rollapply问题。所以接下来我想:
lapply(fileData, function(x) rollapply ......好像有一英里远。欢迎提供一些指导和解决办法。
谢谢。
发布于 2014-06-06 02:37:18
我大汗淋漓,花了一些时间慢慢地了解了如何用另一个函数的参数来分解调用函数的过程和协议。一个伟大的网站,帮助是高级R从一个,也是唯一的哈德利韦翰,再次!显示过程故障的图片接近理想状态。尽管我仍然需要我的思考来了解一些细节。
下面是一个包含注释的完整示例。希望其他人发现它有用。
library(zoo)
#Create a list of dataframes for the example.
listOfDataFrames<- list(mtcars, mtcars, mtcars)
#Give each element a name.
names(listOfDataFrames) <- c("A", "B", "C")
#This is a simple function just for the example!
#I want to perform this function on column 'col' of matrix 'm'.
#Of course to make the whole task worthwhile, this function is usually something more complex.
fApplyFunction <- function(m,col){
mean(m[,col])
}
#This function is called from lapply() and does 'something' to the dataframe that is passed.
#I created this function to keep lapply() very simply.
#The something is to apply the function fApplyFunction(), wich requires an argument 'thisCol'.
fOnEachElement <- function(thisDF, thisCol){
#Convert to matrix for zoo library.
thisMatrix <- as.matrix(thisDF)
rollapply(thisMatrix, 5, fApplyFunction, thisCol, partial = FALSE, by.column = FALSE)
}
#This is where the program really starts!
#
#Apply a function to each element of list.
#The list is 'fileData', with each element being a dataframe.
#The function to apply to each element is 'fOnEachElement'
#The additional argument for 'fOnEachElement' is "vs", which is the name of the column I want the function performed on.
#lapply() returns each result as an element of a list.
listResults <- lapply(listOfDataFrames, fOnEachElement, "vs")
#Combine all elements of the list into one dataframe.
combinedResults <- do.call(cbind, listResults)
#Now that I understand the argument passing, I could call rollapply() directly from lapply()...
#Note that ONLY the additional arguments of rollapply() are passed. The primary argurment is passed automatically by lapply().
listResults2 <- lapply(listOfDataFrames, rollapply, 5, fApplyFunction, "vs", partial = FALSE, by.column = FALSE)结果:
> combinedResults
A B C
[1,] 0.4 0.4 0.4
[2,] 0.6 0.6 0.6
[3,] 0.6 0.6 0.6
[4,] 0.6 0.6 0.6
[5,] 0.6 0.6 0.6
[6,] 0.8 0.8 0.8
[7,] 0.8 0.8 0.8
[8,] 0.8 0.8 0.8
[9,] 0.6 0.6 0.6
[10,] 0.4 0.4 0.4
[11,] 0.2 0.2 0.2
[12,] 0.0 0.0 0.0
[13,] 0.0 0.0 0.0
[14,] 0.2 0.2 0.2
[15,] 0.4 0.4 0.4
[16,] 0.6 0.6 0.6
[17,] 0.8 0.8 0.8
[18,] 0.8 0.8 0.8
[19,] 0.6 0.6 0.6
[20,] 0.4 0.4 0.4
[21,] 0.2 0.2 0.2
[22,] 0.2 0.2 0.2
[23,] 0.2 0.2 0.2
[24,] 0.4 0.4 0.4
[25,] 0.4 0.4 0.4
[26,] 0.4 0.4 0.4
[27,] 0.2 0.2 0.2
[28,] 0.4 0.4 0.4
> listResults
$A
[1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4
$B
[1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4
$C
[1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4
> listResults2
$A
[1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4
$B
[1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4
$C
[1] 0.4 0.6 0.6 0.6 0.6 0.8 0.8 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 0.8 0.6
[20] 0.4 0.2 0.2 0.2 0.4 0.4 0.4 0.2 0.4发布于 2014-06-04 06:56:53
我将尽力帮助您,并向您展示如何调试这个问题。在R中非常有用的一个技巧是学习如何调试。我正在使用browser函数。
问题:
在这里,我通过添加一行来更改函数f:
f <- function(x) {
browser()
PPI(x$changeFactor_A, x$changeFactor_B)
}现在你跑的时候:
rollapply(df, 1, f)调试器停止,您可以检查参数x的值:
Browse[1]> x
[1,]
1e+05 正如您看到的是一个标量值,所以您不能在上面应用$运算符,因此您得到了错误:
Error in x$changeFactor_A : $ operator is invalid for atomic vectors 一般指南
现在我来解释一下你该怎么做。
excees:所以在它之外执行减法(更容易)mapply获得一个广义解。(难度更大,但更笼统,非常有用)$。就我个人而言,我只在R控制台上使用它。完整解决方案:
我假设您的data.frames(动物园对象)有changeFactor_A和changeFactor_B列。
sapply(fileData,function(dat){
dat <- transform(dat,excess= changeFactor_A-changeFactor_B)
rollapply(dat[,'excess'],2,sum)
}或更广泛地说:
sapply(fileData,function(dat){
excess <- get_excess(dat,'changeFactor_A','changeFactor_B')
rollapply(excess,2,sum)
}哪里
get_excess <-
function(data,colA,colB){
### do whatever you want here
### return a vector
excess
}发布于 2014-06-04 06:56:58
查看?rollapply帮助页面的“使用”部分。我承认R帮助页面并不容易解析,我也知道你是如何感到困惑的。
问题是rollapply可以处理ts、zoo或一般的numeric向量,但只能处理一个系列。您正在为它提供一个函数,它包含两个参数,asset和benchmark。当然,您的f和PPI可以很小地被矢量化,但是rollapply并不是为此而做的。
解决方案:在rollapply之外计算您的excess (excess很容易向向量计算,并且不涉及任何滚动计算),然后才将您的函数提交给它:
> mtcars$excess <- mtcars$mpg-mtcars$disp
> rollapply(mtcars$excess, 3, sum)
[1] -363.2 -460.8 -663.1 -784.8 -893.9 ...您可能对mapply感兴趣,它将多个参数的函数向量化,类似于处理单个参数的apply和朋友。然而,我知道没有类似于滚动窗口的mapply。
https://stackoverflow.com/questions/24029937
复制相似问题