2013-05-10 38 views
3

當我把一個值當作一個變量和一個R中的字符串時,我感到困惑。在Ruby和Python中,我習慣於一個總是被引用的字符串,並且一個未加引號的字符串總是被視爲一個變量。 IE瀏覽器。R中內聯的變量擴展

a["hello"] => a["hello"] 
b = "hi" 
a[b] => a["hi"] 

但在R,不是這種情況下,例如

a$b < c(1,2,3) 

B給是列,而不是變量b的值/名稱。

c <- "b" 
a$c => column not found (it's looking for column c, not b, which is the value of the variable c) 

(我知道,在這種特定的情況下,我可以使用[C],但也有許多其他情況下,如ggplot(a, aes(x=c)) - 我要繪製是c的值,不與列名稱c)...

在其他StackOverflow的問題,我已經看到了像報價,替代等提到的東西。

我的問題是:是否有一種「擴展」變量並確保使用變量的值而不是變量的名稱的一般方法?或者,這不僅僅是R在做什麼?

+0

我認爲'get',在下面提到,在技術上是最「普遍」的解決方案。但_correct_答案可能會因不同情況而有所不同。例如請參閱我的評論,關於在ggplot中不使用'aes_string'的可怕性。 – joran 2013-05-10 15:51:50

+0

@joran我同意,但我不認爲用'$'操作符做這件事是否有正確的方法。 – 2013-05-10 22:21:25

+0

你可能會覺得這有幫助:https://github.com/hadley/devtools/wiki/Computing-on-the-language(它仍然是一個正在進行的工作) – hadley 2013-05-10 22:59:01

回答

3

在你的榜樣,a$ba[["b"]]語法糖。與列表一起使用時,這是$符號的特殊功能。第二種形式做你期望的 - a[[b]]將返回a的元素,其名稱== 變量b的值,而不是名稱爲「b」的元素。

數據幀是相似的。對於數據幀a$運算符引用列名稱。所以a$ba[ , "b"]相同。在這種情況下,要參考由指示的a的列b,請使用a[, b]

+0

對不起,'[['是我想要的。我糾正了答案。 – Tyler 2013-05-10 16:35:39

0

如果要獲取名爲「b」的變量,請在每種情況下使用get函數。這將取代b的值得到(b)無論發現在哪裏。

+0

雖然不適用於所有事情。 'a < - 「mpg」; mtcars $ get(a)' – Dason 2013-05-10 15:45:56

+2

我不會推薦在某些特定情況下使用'get',例如'ggplot',在正確的解決方案中使用'aes_string'。 – joran 2013-05-10 15:48:16

+0

@joran我不經常使用ggplot2。我希望我知道'aes_string' - 一段時間後,我使用''eval''和'parse'來做我想做的事情......讓我們開始迴避...... – Dason 2013-05-10 16:19:06

0

如果你想玩表達式,你需要使用quote(),substitute(),bquote()和像你提到的朋友。

例如:

x <- quote(list(a = 1)) 
names(x) # [1] "" "a" 
names(x) <- c("", a) 
x # list(foo = 1) 

和:

c <- "foo" 
bquote(ggplot(a, aes(x=.(c)))) # ggplot(a, aes(x = "foo")) 
substitute(ggplot(a, aes(x=c)), list(c = "foo")) 
+0

您的'ggplot'示例很聰明,但很糟糕,絕不應該這樣做。 – joran 2013-05-10 15:50:02

2

您發佈的關於$運營商不起作用的原因非常微妙,通常與R中的大多數其他情況完全不同,因爲您可以使用像get這樣的功能,該功能是專爲此目的設計的。但是,調用a$b相當於調用

`$`(a , b) 

這提醒我們,在R,一切是一個對象。 $是一個函數,它有兩個參數。如果我們檢查源代碼,我們可以看到,調用a$c,並期望R鍵評估c"b"從未的工作,因爲在源代碼中就指出:

/* The $ subset operator. 
    We need to be sure to only evaluate the first argument. 
    The second will be a symbol that needs to be matched, not evaluated. 
*/ 

它實現此使用以下:

if(isSymbol(nlist)) 
SET_STRING_ELT(input, 0, PRINTNAME(nlist)); 
else if(isString(nlist)) 
SET_STRING_ELT(input, 0, STRING_ELT(nlist, 0)); 
else { 
errorcall(call,_("invalid subscript type '%s'"), 
     type2char(TYPEOF(nlist))); 
} 

nlist是你通過do_subset_3參數(C函數$映射到的名稱),在這種情況下c。它發現c是一個符號,所以它用一個字符串替換它,但是沒有對它進行評估。如果它是一個字符串,那麼它作爲一個字符串傳遞。

2

這裏有一些鏈接,以幫助你理解「爲什麼」和'當R.評價他們可能是啓發性的,甚至還有可能幫助,如果不出意外,他們將讓你知道,你並不孤單:

http://developer.r-project.org/nonstandard-eval.pdf

http://journal.r-project.org/2009-1/RJournal_2009-1_Chambers.pdf

http://www.burns-stat.com/documents/presentations/inferno-ish-r/

在這最後一個,最重要的一條是子彈2點,然後通過全組幻燈片閱讀。我可能會從第三個開始,然後是第一個2.

這些不是本着如何使一個特定的案例工作(如其他答案已經完成)的精神,更多的是本着導致這種情況以及爲什麼在某些情況下,有標準的非標準訪問變量的方法是有意義的。希望瞭解爲什麼以及何時將幫助整體做什麼。

+0

+1感謝您的有趣的要點。伯恩斯的談話一如既往的令人愉快。我必須指出我的回答中心爲什麼OP發佈*無法工作,而不是如何使其工作。 – 2013-05-10 21:50:29