簡體   English   中英

R:在函數參數中為一般(通用)使用的函數指定變量名

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM