build议化学家:自动化/简化他的伏安数据graphics代码

我是最近处理大量伏安数据的化学家。 让我非常清楚,并提供一些研究资料。 我在固态导电薄膜上从起始电压扫描到结束电压。 这些扫描将保存为.txt文件(名称scheme:运行#.txt)在一个文件夹中。 我正在研究电导随温度变化如何变化。 LINEST线描绘给定温度下的电stream与电压的关系,给出一条斜率=电导的线。 一旦我有每次扫描的电导(斜率),我绘制电导与温度,以查看依赖于温度的电导特性。 我一直在Excel中这样做,但已经find了使用R完成工作的更快捷的方法。我对R(Rstudio)是全新的,并认识到我的编码不是最好的。 毫无疑问,这个过程可以精简和加速,这将非常有帮助。 这是我目前正在执行的过程:

# Set working directory with folder containing all .txt files for inspection # Add all .txt files to the global environment allruns<-list.files(pattern=".txt") for(i in 1:length(allruns))assign(allruns[i],read.table(allruns[i])) 

由于所有运行的电压列(1×1000matrix)是相同的,并且在每个.txt文件的列V1中,我将ax指定为来自第一个文件夹的电压列

 x<-run1.txt$V1 

所有.txt文件中的所有电stream(这些随电压变化而变化)都在V2列中find,所以我给每个文件分配了y#。 这些一次input一个..

 y1<-run1.txt$V2 y2<-run2.txt$V2 y3<-run3.txt$V2 # ... yn<-runn.txt$V2 

这样我就可以得到每个LINEST的eqn(每个扫描一个LINEST,稍后用abline绘制)。 再次进入一个:

 run1<-lm(y1~x) run2<-lm(y2~x) run3<-lm(y3~x) # ... runn<-lm(yn~x) 

为了在同一个图上得到一个包含所有LINEST(每个扫描一个)的单个图,没有显示数据点,我一直在使用这种编码模式,首先将所有的数据点在单独一个系列中:

 plot(x,y1,col="transparent",main="LSV Solid Film", xlab = "potential(V)",ylab="current(A)", xlim=rev(range(x)),ylim=range(c(y3,yn))) par(new=TRUE) plot(x,y2,col="transparent",main="LSV Solid Film", xlab = "potential(V)",ylab="current(A)", xlim=rev(range(x)),ylim=range(c(y3,yn))) par(new=TRUE) plot(x,y3,col="transparent",main="LSV Solid Film", xlab = "potential(V)",ylab="current(A)", xlim=rev(range(x)),ylim=range(c(y1,yn))) # ... par(new=TRUE) plot(x,yn,col="transparent",main="LSV Solid Film", xlab = "potential(V)",ylab="current(A)", xlim=rev(range(x)),ylim=range(c(y1,yn))) #To obtain all LINEST lines (one for each scan, on the single graph): abline(run1,col=””, lwd=1) abline(run2,col=””,lwd=1) abline(run3,col=””,lwd=1) # ... abline(runn,col=””,lwd=1) # Then to get each LINEST equation: summary(run1) summary(run2) summary(run3) # ... summary(runn) 

每次使用summary() ,我都复制斜率并将其粘贴到Excel工作表中 – 以及单独logging的相应扫描温度。 然后,我将这个电影的电导v温度点作为平滑线的XY散射图,给出与温度相关的电导曲线。 在R中给我一个单独的LINEST线图,在Excel中给出电导温度。

这项技术实际上比在Excel中完成这项技术要快得多,但它可以更快,更高效地完成! 另外,如果我需要改变一些东西,整个过程都需要重新执行,不pipe有什么变化。 这个过程需要我5个小时的Excel和1.5个小时的R(也许我太慢了)。 尽pipe如此,任何提示,以帮助进一步自动化/精简这是非常值得赞赏的。

list的数据操作有很多问题。 存储一个matrix列表或一个数据列表。 data.frame速度很快,而且可以很容易地将一个干净地运行的代码应用到其余的n-1

(注意:我在这里展示的方法是一种技术:将所有内容保存在分隔良好的列表中,其他人会build议 – 非常合理 – 将事物组合到一个数据data.frame并添加一个groupvariables哪个文件/实验的数据来源)将有助于更先进的多实验回归或组合绘图,如与ggplot2 。我不打算在这里进入这后一种技术,还没有。

  1. 长期以来,不要for(...) assign(..., read.csv(...)) 。 你有重要的部分完成,所以这是相对容易的:

     allruns <- sapply(list.files(pattern = "*.txt"), read.table, simplify = FALSE) 

    (使用sapply(..., simplify=FALSE)lapply(...)类似,但是在这种情况下,每个文件名都有一个很好的副作用。在这里可能并不重要,但在其他地方相当方便。)

  2. 提取你的不变和可变数据是很简单的:

     allLMs <- lapply(allruns, function(mdl) lm(V2 ~ V1, data = mdl)) 

    我在这里使用每个表的V1 ,而不是一次提取的x …虽然你可能想知道为什么,我认为保留它有两个原因:(1)只是在情况下, V1variables甚至是一行不同,这会拯救你; (2)像这样构build模型是很容易的。

    此时, allLMs中的每个对象都是lm对象,这意味着我们可以这样做:

     summary(allLMs[[1]]) 
  3. 绘图:我想我明白你为什么使用par=NEW ,我不得不笑…在开始使用这种技术之前,我已经深入R了一段时间。 我认为你需要的其实是简单得多:

     xlim <- rev(range(allruns[[1]]$V1)) ylim <- range(sapply(allruns, `[`, "V2")) # this next plot just sets the box and axes, no points plot(NA, type = "na", xlim = xlim, ylim = ylim) # no need to plot points with "transparent" ... ign <- sapply(allLMs, abline, col = "") # and other abline options ... 
  4. 将所有模型复制到Excel中,再次使用列表:

     out <- do.call(rbind, sapply(allLMs, function(m) summary(m)$coefficients[,1])) 

    这将是一个单一的数据框,所有的系数在两列。 (可以使用类似的技术来提取其他模型摘要属性,包括std errt.value或者Pr(>|t|) (在$coefficients );或者$r.squared$adj.r.squared等)

     write.csv(out, file="clipboard", sep="\t") 

    并粘贴到Excel中。 (或者,更好的办法是将其保存到CSV文件并导入,因为您可能需要保留它。)

使用列表的一个诀窍就是坚持下去:尽可能将事情保存在列表中,这样就不会单独处理模型。 一个咒语是,如果你做了一次,你不应该再次键入它,只是循环/应用/地图/任何。 在必要之前不要从列表中提取太多。

注:r2evans的答案提供了很好的一般性build议,不需要繁重的包依赖。 但是看到替代策略可能并不会造成伤害。

对于这种事情来说,这种反转是非常方便的,下面是一个虚拟的例子,

 library(tidyverse) # creating dummy data files dummy <- function(T) { V <- seq(-5, 5, length=20) I <- jitter(T*V + T, factor = 1) write.table(data.frame(V=V, I = I), file = paste0(T,".txt"), row.names = FALSE) } purrr::walk(300:320, dummy) # reading lf <- list.files(pattern = "\\.txt") read_one <- function(f, ...) {cbind(T = as.numeric(gsub("\\.txt", "", f)), read.table(f, ...))} m <- purrr::map_df(lf, read_one, header = TRUE, .id="id") head(m) ggplot(m, aes(V, I, group = T)) + facet_wrap( ~ T) + geom_point() + geom_smooth(se = FALSE) 

在这里输入图像说明

 models <- m %>% split(.$T) %>% map(~lm(I ~ V, data = .)) coefs <- models %>% map_df(broom::tidy, .id = "T") ggplot(coefs, aes(as.numeric(T), estimate)) + geom_line() + facet_wrap(~term, scales = "free") 

在这里输入图像说明