使用计数器在mapply调用中以ggtitle的方式访问命名列表元素

时间:2018-11-23 14:55:12

标签: r mapply

我正在基于两个列表中的数据生成并绘制多个ggplots,因此我正在使用mapply。列表之一具有命名元素,我想将其用作ggtitle。但这只是所有图的第一个元素

> names(sample_subset_list)
[1] "water after day 43 dna min reads per OTU 5"
[2] "biofilm after day 43 dna min reads per OTU 5"
[3] "water after day 43 cdna min reads per OTU 5"
[4] "biofilm after day 43 cdna min reads per OTU 5"
[5] "water after day 44 dna min reads per OTU 5"
[6] "biofilm after day 44 dna min reads per OTU 5"
[7] "water after day 44 cdna min reads per OTU 5"
[8] "biofilm after day 44 cdna min reads per OTU 5"

这是绘图功能:

ordination_plots <- list()
counter <- 0
ordination_plots <- mapply(function(x,y,counter) {
                        counter <- counter + 1 
                        plot_ordination(x, y, type = "sample") + 
                            ggtitle(names(sample_subset_list)[counter]) +
}, x = sample_subset_list, y = ordination_nmds, counter = 0, SIMPLIFY = FALSE)

这将为我提供情节,其中标题始终是

的第一个元素

names(sample_subset_list)

调用ggtitle(names(sample_subset_list)[]) +

时也会发生

如果我使用counter <<-(在这里建议:Using a counter inside an apply structured loop in R)或致电ggtitle之类的话

ggtitle(names(sample_subset_list)) +

ggtitle(names(sample_subset_list)[[]]) +

我根本没有标题。

我开始时没有计数器,这也给了我所有情节的相同头衔。有人可以给我解释一下如何迭代列表元素的名称以将其用于ggplots吗?

1 个答案:

答案 0 :(得分:2)

让我们减少示例的复杂性:

counter <- 0

invisible(mapply(function(letter, counter) {

  counter <- counter + 1
  cat("Letter: ", letter, "; Counter: ", counter, "\n", sep="")

}, letters[1:10], counter))

注意:我只使用invisible()来停止打印mapply()的结果。

letters[1:10]是由10个元素组成的小写字母矢量(内置数据)。

您在counter之外定义mapply()。与forwhile不同,mapply()中的函数默认情况下不会在父作用域(mapply()之外)中创建或修改变量,因此结果是: / p>

Letter: a; Counter: 1
Letter: b; Counter: 1
Letter: c; Counter: 1
Letter: d; Counter: 1
Letter: e; Counter: 1
Letter: f; Counter: 1
Letter: g; Counter: 1
Letter: h; Counter: 1
Letter: i; Counter: 1
Letter: j; Counter: 1

可以将带有信息的第二个参数传递给mapply()的函数参数,但是如果目的是增加mapply()中函数范围之外的东西会产生副作用,则您真的不应该将其作为参数传递给它,而只是使用<<-运算符对其进行修改,该运算符是-根据帮助页面:

”运算符<<-->>通常仅在函数中使用,并导致在父环境中搜索要分配的变量的现有定义。找到变量(并且其绑定未锁定),然后重新定义其值,否则将在全局环境中进行分配。”

所以,我们可以这样做:

# TO MY FUTURE SELF AND TEAM MEMBERS
# `counter` is modified as a side-effect of operations in the `mapply()`
# that follows the object declaration
counter <- 0

invisible(mapply(function(letter) {

  counter <<- counter + 1
  cat("Letter: ", letter, "; Counter: ", counter, "\n", sep="")

}, letters[1:10]))

得到这个:

Letter: a; Counter: 1
Letter: b; Counter: 2
Letter: c; Counter: 3
Letter: d; Counter: 4
Letter: e; Counter: 5
Letter: f; Counter: 6
Letter: g; Counter: 7
Letter: h; Counter: 8
Letter: i; Counter: 9
Letter: j; Counter: 10

此评论不适合Snark。您正在使用的副作用可能对您将来的个人或与您共享代码的人们不明显,因此请注意,它将有助于您重新设计外观并弄清楚正在发生的事情。