R:如何从数据集的组合中执行更复杂的计算?

时间:2016-06-15 17:09:35

标签: r loops combn

现在,我有一个来自内置数据集iris的组合。到目前为止,我已被引导能够找到这对值的lm()系数。

myPairs <- combn(names(iris[1:4]), 2)

formula <- apply(myPairs, MARGIN=2, FUN=paste, collapse="~")

model <- lapply(formula, function(x) lm(formula=x, data=iris)$coefficients[2])

model

但是,我想进一步使用lm()中的系数来进一步计算。我想做这样的事情:

Coefficient <- lm(formula=x, data=iris)$coefficients[2]
Spread <- myPairs[1] - coefficient*myPairs[2]
library(tseries)
adf.test(Spread)

程序本身很简单,但我无法为数据集中的每个组合找到一种方法。 (作为旁注,adf.test不适用于此类数据,但我只是使用虹膜数据集进行演示)。 我想知道,为这样的程序编写一个循环会更好吗?

3 个答案:

答案 0 :(得分:2)

听起来你想编写自己的函数并在myPairs循环中调用它(应用):

yourfun <- function(pair){
  fm <- paste(pair, collapse='~')
  coef <- lm(formula=fm, data=iris)$coefficients[2]
  Spread <- iris[,pair[1]] - coef*iris[,pair[2]] 
  return(Spread)
} 

然后你可以调用这个函数:

model <- apply(myPairs, 2, yourfun)

我认为这是最干净的方式。但我不知道你究竟想做什么,所以我正在为Spread编写例子。请注意,在我的示例中,您会收到警告消息,因为列Species是一个因素。

答案 1 :(得分:2)

您可以在combn内完成所有这些操作。

如果您只想对所有组合运行回归,并提取第二个系数

fun <- function(x) coef(lm(paste(x, collapse="~"), data=iris))[2]
combn(names(iris[1:4]), 2, fun)

然后,您可以扩展该功能以计算点差

fun <- function(x) {
         est <- coef(lm(paste(x, collapse="~"), data=iris))[2]
         spread <- iris[,x[1]] - est*iris[,x[2]]
         adf.test(spread)
        }

out <- combn(names(iris[1:4]), 2, fun, simplify=FALSE)
out[[1]]

#   Augmented Dickey-Fuller Test

#data:  spread
#Dickey-Fuller = -3.879, Lag order = 5, p-value = 0.01707
#alternative hypothesis: stationary

将结果与手动运行第一个结果进行比较

est <- coef(lm(Sepal.Length ~ Sepal.Width, data=iris))[2]
spread <- iris[,"Sepal.Length"] - est*iris[,"Sepal.Width"]
adf.test(spread)

#   Augmented Dickey-Fuller Test

# data:  spread
# Dickey-Fuller = -3.879, Lag order = 5, p-value = 0.01707
# alternative hypothesis: stationary

答案 2 :(得分:1)

一些提示:我不会说出与内置函数同名的内容(modelformula会在您的原始版本中出现。

此外,您可以简化您正在执行的paste - 请参阅下文。

最后,一个更一般的陈述:不要觉得所有事情都需要在某种*apply中完成。有时简洁和短代码实际上更难理解,并且记住,*apply函数提供了最好的,边际速度增益,而不是简单的for循环。 (R的情况并非总是如此,但现在正是这样。)

# Get pairs
myPairs <- combn(x = names(x = iris[1:4]),m = 2)

# Just directly use paste() here
myFormulas <- paste(myPairs[1,],myPairs[2,],sep = "~")

# Store the models themselves into a list
# This lets you go back to the models later if you need something else
myModels <- lapply(X = myFormulas,FUN = lm,data = iris)

# If you use sapply() and this simple function, you get back a named vector
# This seems like it could be useful to what you want to do
myCoeffs <- sapply(X = myModels,FUN = function (x) {return(x$coefficients[2])})

# Now, you can do this using vectorized operations
iris[myPairs[1,]] - iris[myPairs[2,]] * myCoeffs[myPairs[2,]]

如果我理解正确,我相信上述方法会奏效。请注意,目前输出上的名称将是荒谬的,您需要将它们替换为您自己设计的内容(可能是myFormulas的值)。