【问题标题】:Use a loop or a function to run a script over multiple files using R [duplicate]使用循环或函数使用 R [重复] 在多个文件上运行脚本
【发布时间】:2013-01-29 08:24:42
【问题描述】:

可能重复:
Which is the best method to apply a script repetitively to n .csv files in R?

我有一个脚本可以计算内核利用率分布并生成摘要图的 PDF。我的脚本目前按每个“周期”拆分数据库,并使用 for 循环生成 KUD 图。我还有多个 csv 文件存储在与单个鱼相对应的目录中。我想要的是使用函数或循环来读取目录中的所有文件并运行脚本,该脚本将为每条鱼和每个时期生成 PDF 图。

我的脚本如下所示:

library(ks)

dd<-read.table(text="period  dist   depth
            1   4916.64 8.661827
            1   4916.64 14.789091
            1   4916.64 13.555909
            1   4916.64 12.92816
            1   4916.64 11.708774
            1   4916.64 15.28
            1   4916.64 13.369875
            1   4916.64 14.039655
            1   4916.64 13.454545
            1   4916.64 12.638261
            1   4916.64 13.251081
            1   4916.64 14.006341
            1   4916.64 12.64
            1   4916.64 15.521818
            1   4916.64 10.202121
            1   4916.64 14.816667
            1   4916.64 15.504
            1   9674.844    23.93
            1   11000.151   22.157143
            1   11414.31    22.72
            1   11414.31    25.7
            1   11414.31    19.07
            1   11414.31    23.085714
            1   9481.57 17.266667
            1   11414.31    26.8
            1   11414.31    19.382222
            1   5616.09 12.016667
            1   10658.02    18.873913
            1   11414.31    25.2
            1   11414.31    20.9
            1   11414.31    27.65
            1   11414.31    22.133333
            1   11414.31    30.9
            1   5616.09 23.3
            2   11172.718   20.391667
            2   9964.755    23.51
            2   5616.09 19.43
            2   5616.09 19.1
            2   4916.64 18.42
            2   8515.2  17.683333
            2   11414.31    22.128571
            2   11414.31    22.8608
            2   10391.095   24.955882
            2   10931.125   25.225
            2   6444.407    20.228571
            2   11276.257   23.77619
            2   10585.993   23.285714
            2   10641.214   20.653333
            2   9757.676    24.007143
            2   11414.31    18.817
            2   11414.31    23.525
            2   11414.31    22.873684
            2   11414.31    26.15
            2   10486.595   21.9
            2   11000.151   24.142857
            2   11414.31    24.3875
            2   10819.621   20.569231
            2   10360.088   29.345455
            2   9708.951    21.488235
            2   11414.31    30.775
            2   11414.31    25.5
            2   11414.31    18.477917
            2   10327.144   26.8625
            2   11414.31    26.12963
            2   11414.31    29.28125
            2   11414.31    23.166667
            2   10689.532   21.8625
            2   11414.31    28.328571
            2   11414.31    22.563158
            2   11414.31    25.490909
            2   11414.31    26.0625
            2   11414.31    34.5
            2   11414.31    17.375294
            ",header=T)

dd1<-data.frame(dd$period,dd$dist,dd$depth)

# split database for each period
period<-dd1$dd.period
M<-split(dd1,period)
l<-length(M)

# run loop through each tag and create a PDF file with all KUD plots
pdf("KUD plot.pdf",width=11,height=8,paper="a4r")
par(mfcol=c(1,1))

for(j in 1:l){

# calculate the 2D kernel
dd2<-data.frame(M[[j]]$dd.dist,M[[j]]$dd.depth)

## auto bandwidth selection
H.pi2<-Hpi(dd2,binned=TRUE)*1
ddhat<-kde(dd2,H=H.pi2)

# Kernel contour plot
plot(ddhat,cont=c(95),drawpoints=TRUE,col="black",xlab="Distance (m)",lwd=2.5, 
    ylab="Depth (m)",ptcol="grey15",cex=0.7,
    xlim=c(min(dd2[,1]-dd2[,1]*0.4),max(dd2[,1]+dd2[,1]*0.4)),ylim=c(45,-1),
    main=paste("Period"," - ",M[[j]]$dd.period[1])) 

plot(ddhat,cont=c(25),add=TRUE,col="red",lwd=2.4)
plot(ddhat,cont=c(50),add=TRUE,col="seagreen2",lwd=2.4)
plot(ddhat,cont=c(75),add=TRUE,col="royalblue",lty=5,lwd=2.5)  

}

dev.off()

任何关于如何改进脚本的建议或想法都将不胜感激。提前致谢!

【问题讨论】:

  • 绝对重复。也没有看到 OP 尝试解决任何问题。

标签: r file function loops


【解决方案1】:

@RomanLustrik 链接的答案不包含基于apply 的解决方案,因此我将在此处介绍一个。您可能想要的功能是来自plyr 包的d*plyplyr 完成所有 splitting-applying a function to each split-and combining it back together again。例如,要获得每个周期的平均深度:

library(plyr)
ddply(dd, .(period), summarise, mn = mean(depth))

您可以使用相同的想法进行分析:

res = dlply(dd, .(period), function(x) {
   dd2 = x[-1]
   H.pi2<-Hpi(dd2,binned=TRUE)*1
   ddhat<-kde(dd2,H=H.pi2)
 })

其中res 是一个长度为2 的列表,其中包含分析结果。您可以使用类似的方法从res 中提取信息,并绘制它。我会为此使用ggplot2

【讨论】:

    【解决方案2】:

    简化代码的一种方法是将for 循环替换为从plyr 包中调用ddply。例如:

    library(plyr)
    
    pdf("test.pdf",width=11,height=8,paper="a4r")
    invisible(ddply(dd1, .(period), function(df) {
      period <- df$dd.period[1]
      df <- df[,-1]
      ## auto bandwidth selection
      H.pi2<-Hpi(df,binned=TRUE)*1
      ddhat<-kde(df,H=H.pi2)
    
      ## Kernel contour plot
      plot(ddhat,cont=c(95),drawpoints=TRUE,col="black",xlab="Distance (m)",lwd=2.5, 
           ylab="Depth (m)",ptcol="grey15",cex=0.7,
           xlim=c(min(df$dd.dist-df$dd.dist*0.4),max(df$dd.dist+df$dd.dist*0.4)),ylim=c(45,-1),
           main=paste("Period"," - ",period)) 
    
      plot(ddhat,cont=c(25),add=TRUE,col="red",lwd=2.4)
      plot(ddhat,cont=c(50),add=TRUE,col="seagreen2",lwd=2.4)
      plot(ddhat,cont=c(75),add=TRUE,col="royalblue",lty=5,lwd=2.5)  
    
    }))
    dev.off()
    

    然后你可以将这段代码包装到你自己的函数中,它将一个数据框和一个 pdf 文件名作为参数:

    pdfks <- function(dd1, filename) {
      pdf(filename, width=11, height=8, paper="a4r")
      ...
      dev.off()
    }
    

    然后您可以创建一个循环,依次加载每个 csv 文件并将此函数应用于每个文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-04
      • 2012-01-17
      • 2015-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多