[英]R: specifying variable name in function parameter for a function of general (universal) use
這是我的小功能和數據。 請注意,我想設計一個非一般用途的功能。
dataf <- data.frame (A= 1:10, B= 21:30, C= 51:60, D = 71:80)
myfun <- function (dataframe, varA, varB) {
daf2 <- data.frame (A = dataframe$A*dataframe$B,
B= dataframe$C*dataframe$D)
anv1 <- lm(varA ~ varB, daf2)
print(anova(anv1))
}
myfun (dataframe = dataf, varA = A, varB = B)
Error in eval(expr, envir, enclos) : object 'A' not found
它適用於我指定數據$ variable name,但我不想制作這樣的規范,因此它要求用戶在函數中寫入數據和變量名。
myfun (dataframe = dataf, varA = dataf$A, varB = dataf$B)
Analysis of Variance Table
Response: varA
Df Sum Sq Mean Sq F value Pr(>F)
varB 1 82.5 82.5 1.3568e+33 < 2.2e-16 ***
Residuals 8 0.0 0.0
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Warning message:
In anova.lm(anv1) :
ANOVA F-tests on an essentially perfect fit are unreliable
這種情況下的最佳做法是什么? 我可以將數據框附加到函數內嗎? 這樣做有什么不利或潛在的沖突/危險? 請參閱輸出中的masked語句。 我相信一旦附上會繼續提醒會話權嗎? 這里提供的功能只是示例,我需要更多的下游分析,其中來自不同數據幀的變量名稱可以是/應該是相同的。 我期待一個程序員解決方案。
myfun <- function (dataframe, varA, varB) {
attach(dataframe)
daf2 <- data.frame (A = A*B, B= C*D)
anv1 <- lm(varA ~ varB, daf2)
return(anova(anv1))
}
myfun (dataframe = dataf, varA = A, varB = B)
The following object(s) are masked from 'dataframe (position 3)':
A, B, C, D
Analysis of Variance Table
Response: varA
Df Sum Sq Mean Sq F value Pr(>F)
varB 1 82.5 82.5 1.3568e+33 < 2.2e-16 ***
Residuals 8 0.0 0.0
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Warning message:
In anova.lm(anv1) :
ANOVA F-tests on an essentially perfect fit are unreliable
讓我們調查(參見我添加的評論)您原始函數和調用,假設您的意思是將您感興趣的列的名稱傳遞給函數:
myfun <- function (dataframe, varA, varB) {
#on this next line, you use A and B. But this should be what is
#passed in as varA and varB, no?
daf2 <- data.frame (A = dataframe$A*dataframe$B, B=dataframe$C*dataframe$D)
#so, as a correction, we need:
colnames(daf2)<-c(varA, varB)
#the first argument to lm is a formula. If you use it like this,
#it refers to columns with _names_ varA and varB, not as names
#the _contents_ of varA and varB!!
anv1 <- lm(varA ~ varB, daf2)
#so, what we really want, is to build a formula with the contents
#of varA and varB: we have to this by building up a character string:
frm<-paste(varA, varB, sep="~")
anv1 <- lm(formula(frm), daf2)
print(anova(anv1))
}
#here, you pass A and B, because you are used to being able to do that in a formula
#(like in lm). But in a formula, there is a great deal of work done to make that
#happen, that doesn't work for most of the rest of R, so you need to pass the names
#again as character strings:
myfun (dataframe = dataf, varA = A, varB = B)
#becomes:
myfun (dataframe = dataf, varA = "A", varB = "B")
注意:在上面,我保留了原始代碼,因此您可能必須刪除其中一些以避免您最初獲得的錯誤。 您的問題的本質是您應該始終將列名稱作為字符傳遞,並使用它們。 這是R中公式的語法糖使人們陷入不良習慣和誤解的地方之一......
現在,作為替代方案:實際使用變量名稱的唯一位置在公式中。 因此,如果您不介意稍后可以清理的結果中存在一些輕微的外觀差異,您可以進一步簡化問題:您無需傳遞列名!
myfun <- function (dataframe) {
daf2 <- data.frame (A = dataframe$A*dataframe$B, B=dataframe$C*dataframe$D)
#now we know that columns A and B simply exist in data.frame daf2!!
anv1 <- lm(A ~ B, daf2)
print(anova(anv1))
}
作為最后一條建議:我不會在你的最后一個聲明中調用print:如果你不這樣做,但是直接從R命令行使用這個方法,它仍會為你執行打印。 作為一個額外的優點,您可以使用從方法返回的對象執行進一步的工作。
試用清理功能:
dataf <- data.frame (A= 1:10, B= 21:30, C= 51:60, D = 71:80)
myfun <- function (dataframe, varA, varB) {
frm<-paste(varA, varB, sep="~")
anv1 <- lm(formula(frm), dataframe)
anova(anv1)
}
myfun (dataframe = dataf, varA = "A", varB = "B")
myfun (dataframe = dataf, varA = "A", varB = "D")
myfun (dataframe = dataf, varA = "B", varB = "C")
你總是可以去(恐怖) parse()
路線:
Rgames: foo<- data.frame(one=1:5,two=6:10)
Rgames: bar <- function(y) eval(parse(text=paste('foo$',y,sep='')))
也就是說,在函數內部,獲取函數的參數,並使用eval(parse(...))設置構建內部數據框或所需數據向量對。
我不確定完全理解你的問題,所以這就是我所理解的:你希望你的函數調用lm()
函數來處理從作為參數給出的data.frame中提取的數據,以及這個data.frame中的列由其他參數指定?
對我來說,最簡單的解決方案是模仿lm()
行為並向用戶詢問公式:
dataf <- data.frame(A=1:10, B=21:30, C=51:60, D=71:80)
myfun <- function(formula, dataframe) {
daf2 <- data.frame(A=dataframe$A*dataframe$B, B=dataframe$C*dataframe$D)
anv1 <- lm(formula=formula, data=daf2)
print(anova(anv1))
}
myfun(formula=A~B, dataframe=dataf)
另一種解決方案是自己構建公式:
dataf <- data.frame(A=1:10, B=21:30, C=51:60, D=71:80)
myfun <- function(dataframe, varA, varB) {
daf2 <- data.frame(A=dataframe$A*dataframe$B, B=dataframe$C*dataframe$D)
frm = as.formula(sprintf("%s~%s", varA, varB))
anv1 <- lm(frm, daf2)
print(anova(anv1))
}
myfun(dataframe=dataf, varA="A", varB="B")
我對attach
不太熟悉,但我盡可能避免它,因為你提到的掩蓋問題。 如果你在功能結束時detach
它我認為它不會導致邊界效果,但你也可以發出警告。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.