使用 lapply 时,用于绘制和保存 igraph 对象的函数会跳过列表元素

Function for plotting and saving igraph objects skips list elements when using lapply

我有一个网络对象列表,我想浏览该列表,绘制每个网络并将绘图保存到我的工作目录。

# creating list of networks
networks <- list()
networks[[1]] <- graph(c("A","B"))
networks[[2]] <- graph(c("C","D"))
networks[[3]] <- graph(c("E","F"))

我想保存到工作目录的预期输出:

# looking at plots
plot(networks[[1]])
plot(networks[[2]])
plot(networks[[3]])

由于我的列表相当长,并且在原始示例中我需要传递一些初始参数,所以我想要一个函数来绘制和保存每个网络,然后 lapply() 将其添加到列表中。这是我尝试过的:

# generating and saving plots automatically
Plotter <- function(network){

        # Generate some random number so plots don´t get overwritten
        Rand <- runif(1,0,100000)

        # setting seed
        set.seed(123)

        # set up picture device
        jpeg(paste(Rand,"NetworkPlot.jpg",sep=""),
             width = 800,
             height = 800,
             units = "px",
             quality = 100)

        # plotting the network
        plot(network)

        # saving to wd
        dev.off()

}

# Applying function to list of networks
lapply(networks,Plotter)

我希望我的工作目录中有三个不同的图。但是,如果我去wd,我只看到第一个和最后一个情节。

起初我认为当相同的 Rand 被选中并且文件被覆盖时,这可能不太可能是巧合。但是我试了好几次,每次都是这样。

鉴于您生成名称的方式,相同的数字生成两次的可能性不大。事实上,它是有保证的。你的代码说:

# Generate some random number so plots don´t get overwritten
Rand <- runif(1,0,100000)

# setting seed
set.seed(123)

第一次执行时会生成一个0到100000之间的随机数,然后设置随机种子为123,第二次执行时会生成一个从种子开始的数123.然后重新设置种子为123,以后每次都会从随机种子123中生成一个数,覆盖除第一个以外的所有之前的结果。所以你得到第一个和最后一个。只需删除设置种子的行,您将得到所有不同的数字,因此得到不同的文件名。

如果您想对此进行测试,请保持代码不变,但添加行

write(paste0(Rand, "\n"), stderr())

就在你生成 Rand 之后。

不是使用在第一个 运行 之后播种的随机数,而是通过遍历 网络 的长度来使用列表的索引号。

具体来说,考虑用 seq_along 调用 lapply 并将整数传递给定义的函数,该函数将用于:1) 不同的文件名和 2) 索引您的列表:networks[[##]] .另外,如果你对任何情节有疑问,你知道问题出在哪一项上!

# generating and saving plots automatically
Plotter <- function(n){    
    # set up picture device
    jpeg(paste0("NetworkPlot_", n, ".jpg"),
         width = 800,
         height = 800,
         units = "px",
         quality = 100)

    # plotting the network
    plot(networks[[n]])

    # saving to wd
    dev.off()    
}

lapply(seq_along(networks), Plotter)

同样,命名列表可以在将字符串传递给函数的相同方面工作:

# NAMING ITEMS: n1, n2, n3, ...
networks <- setNames(networks, paste0("n", seq_along(networks)))

# OUTPUT PLOTS
networks$n1
networks$n2
networks$n3
...

# SAVE PLOTS TO DISK
lapply(names(networks), Plotter)