2014-03-07 72 views
2

最近,我一直在使用lapply和sapply作爲我的前往功能。到目前爲止這麼好,但爲什麼下面的代碼不能阻止我。使用lapply的地塊列表

df<-as.data.frame(matrix(rnorm(50),ncol=5)) 
names(df)<-c("x1","x2","x3","x4","x5") 
df1<-seq_len(10) 

ll<-lapply(seq(1,5), function(i) qplot(df1,df[,i])) 

我得到的錯誤:

Error in `[.data.frame`(df, , i) : undefined columns selected 

好吧,顯然我在可重複的代碼所做的相當不幸的錯誤。它現在有效,但ll列表中的所有圖都是同一個圖。當我運行此:

do.call(grid.arrange,ll)

我獲得下面的圖片:

Grid

所有的情節都是一樣的!這也是我通過我的數據運行時得到的輸出。

+0

它給你什麼錯誤? –

+0

將其添加到答案中。 – Pinemangoes

+1

考慮到您發佈的示例圖,我不會使用'grid.arrange',而是切換到使用facetting('facet_wrap'或'facet_grid')。以我的答案爲例。在我看來,構建更容易和靈活。 –

回答

5

有懶的評價,或者類似的問題呢。你需要做到以下幾點:

ll<-lapply(
    seq(1,5), 
    function(i) qplot(data=data.frame(y=df[, i]), df1, y) 
) 

這將迫使每個情節要更新的y值。

在這個其他的更多討論SO Post

+3

+1!或者完全跳過循環,並使用facetting。這就是'ggplot2'的設計方式。 –

+3

@PaulHiemstra,我同意,雖然在某些情況下ggplot圖的列表實際上是一個有用的東西,但你可能是正確的,在這種情況下,facetted方法是更好的結果。 – BrodieG

+0

謝謝!這解決了它。 – Pinemangoes

3

你告訴它來執行的10列在你只有5本作品:

ll<-lapply(seq(1,5), function(i) qplot(df1,df[,i])) 
+0

謝謝。我編輯了我的第一篇文章,因爲我現在看到了與我的數據集中相同的問題。 – Pinemangoes

+0

看起來有些人已經迴應了你的編輯:) –

4

你的問題與懶惰的評價。這意味着ll中的功能僅在您致電grid.arrange時才真正進行評估。那時,每個函數都會試着找到i,到那時候它的值將會是5,因爲這是lapply循環結束時的最後一個值i。因此,從df提取的數據總是第五列,因此你的圖是完全相同的。

爲了防止出現這種情況,您需要在創建函數時強制執行數據提取,例如使用@ BrodieG的方法。在那裏,創建一個新的data.frame,強制從df獲取數據。或者,您可以使用force強制評估i

參見更多的例子和懶惰評價的解釋:


對於同一個data.frame我會用創建多個列的陰謀facet_wrap。要使用facet_wrap,您需要使用meltreshape2包重新排序數據:

library(ggplot2) 
library(reshape2) 
df$xvalues = 1:10 
df_melt = melt(df, id.vars = 'xvalues') 
ggplot(df_melt, aes(x = xvalues, y = value)) + 
    geom_point() + facet_wrap(~ variable) 

enter image description here

+0

這確實是一個更好的解決方案,因爲它允許我使用更優雅的'ggplot' +'ggsave'組合而不是'qplot' +'grid.arrange'一塌糊塗。感謝您的幫助。 – Pinemangoes

+0

我很少要求使用循環,facetting幾乎總是可以用來獲得相同的結果。 –