2016-02-17 76 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