2016-02-17 114 views
2

我試圖使用sapply添加名稱作爲小區標題傳遞給一系列盒圖的名稱,但遇到了麻煩。sapply函數參數中的循環

首先生成玩具數據來說明問題。

set.seed(12345) 

df <- data.frame(v = rep(letters[1:3], times = 4)) 

for (i in 1:21) { 
    x <- rnorm(12, 3, 1) 
    df <- cbind(df, x) 
    } 

colnames (df)<- c("group", paste(rep(letters[1:7], each = 3), rep(1:3, times = 7), sep = "")) 

這給了我們一個數據集,其中包含按列名的第一個字母聚集的列。這與我自己的數據集類似,其中有一個問卷在多個時間點測量多個項目(很多時間點)。這份問卷產生了幾個因子分數。因此,有幾組列可以代表多次測量問卷的每個因素。在這個玩具數據集中,我們可以將列名稱中的字母看作指示哪個因素,以及指示哪個時間點的數字。

我希望能夠通過sapply函數來選擇我製作箱型圖的哪個簇/因子。所以我需要創建一個列表,其組件是每個列名稱的集羣。

colsList <-list (aCols <- c("a1", "a2", "a3"), 
       bCols <- c("b1", "b2", "b3"), 
       cCols <- c("c1", "c2", "c3"), 
       dCols <- paste("d", 1:3, sep = ""), 
       eCols <- paste("e", 1:3, sep = ""), 
       fCols <- paste("f", 1:3, sep = ""), 
       gCols <- paste("g", 1:3, sep = "")) 

現在製作boxplot函數。我想根據小組製作每個羣集因素的圖。

boxplotFunct <- function (DV, IV, Title) { 
       boxplot(DV ~ IV, main = Title, horizontal = TRUE) 
} 

現在在sapply循環中調用該函數。

par(mfrow = c(1,3)) 

sapply(df[,colsList[[1]]], function(x) boxplotFunct(x, df$group, colsList[[1]])) 

箱線圖工作,但每個boxplot的標題包含所有三個列名稱,而不是相應的列名稱。我仍然在使用sapply時該怎麼做?

我會很樂意提出如何更好地完成整個過程的建議,但我主要想提出一些關於如何解決我的特定問題的建議:在sapply循環中包含另一個循環(例如,這更適用於我關於申請家庭的一般學習,而不是如何繪製圖表)。

回答

1

在迭代colsList[[1]]而不是df[, colsList[[1]]]時,可以大大減少代碼sapply

sapply(colsList[[1]], function(x) { 
    boxplotFunct(df[, x], df$group, x) 
}) 

boxplots


更新:

在回答下面的評論,讓我們假設你想從另一個列表中的字符串替換現有的圖標題。我傾向於使用foreach來執行與sapply非常相似的任務,但允許您指定多個輸入列表。如果您還不熟悉軟件包,請查看Using The foreach Pakage。這裏是一些示例代碼。

## alternate column names 
colsList2 <- list(hCols <- paste("h", 1:3, sep = ""), 
        iCols <- paste("i", 1:3, sep = ""), 
        jCols <- paste("j", 1:3, sep = ""), 
        kCols <- paste("k", 1:3, sep = ""), 
        lCols <- paste("l", 1:3, sep = ""), 
        mCols <- paste("m", 1:3, sep = ""), 
        nCols <- paste("n", 1:3, sep = "")) 

## create plots 
par(mfrow = c(1, 3)) 

library(foreach) 
foreach(x = colsList[[1]], y = colsList2[[1]]) %do% 
    boxplotFunct(df[, x], df$group, y) 

boxplots2

+0

謝謝@fdetsch。十分優雅。這實際上是最有啓發性的。 – llewmills

+0

如果我想用不同於列名的名稱來標記圖,那麼我想從第二個列表中調用這些列名?爲了論證而說出與colsList相同類型的標籤模式,但是從h到n運行。 – llewmills

+0

@llewmills,我更新了上述代碼以迴應您的最新評論。 – fdetsch

1

你可以使用

sapply(seq(lengths(colsList)[[1]]), function(x) 
    boxplotFunct(df[,colsList[[1]][x] ], df$group, colsList[[1]][x])) 

即使用索引。

+0

沒錯。完善。謝謝@lukeA。 – llewmills

+0

我不認爲你可以爲我解構它嗎?我得到了我認爲的x索引,但我不明白你對第一個參數做了什麼(即'seq'和'長度'有什麼作用?) – llewmills

+1

當然。 「長度(colsList)」爲您提供了一個具有列表中每個向量長度的向量(它們都是長度爲3的)。長度(colsList)[1]或長度(colsList [[1]])給出了列表中第一個向量的長度。並且'seq(3)'或者'seq_len(3)'產生一個從1到3的整數序列。你也可以使用'seq_along(colsList [[1]])或者'1:3' - >多種方式實現你的目標。還要注意''長度'等給你一個函數的幫助。 – lukeA