第 2 章 批量处理光合测定数据
对于多数人来讲,一个季节用光合仪测量的数据文件至少是两位数的,处理起来非常不方便,针对这个问题,简单写了一个批量读取 LI-6400 和 LI-6800 原始数据的包(因为现有的容易实现的读取 excel 格式的包还不支持 6800 和 6400 这种形式的公式计算)2,使用非常简单,同时也适合处理未关闭数据文件而导致的无法生成 excel 格式的数据时的问题。
2.1 安装
暂时只有我的 github repo 中的版本:
::install_github("zhujiedong/readphoto") devtools
2.2 LI-6400 数据处理
2.2.1 LI-6400 数据的整合{#6400combine}
基本参数如下:
library(readphoto)
<- read_bat_6400("./data/6400", header_line = 17, data_start = 27) df64
数据输出如下所示(仅显示前8列数据):
files | Obs | HHMMSS | FTime | EBal. | Photo | Cond | Ci | |
---|---|---|---|---|---|---|---|---|
1 | aci | 1 | 10:55:14 | 483.0 | 0 | 6.990 | 0.0831 | 251.0 |
4 | aci | 2 | 10:57:35 | 623.5 | 0 | 5.160 | 0.0853 | 192.0 |
7 | aci | 3 | 10:59:55 | 763.5 | 0 | 3.140 | 0.0881 | 136.0 |
10 | aci | 4 | 11:02:26 | 914.5 | 0 | 0.910 | 0.0927 | 81.9 |
13 | aci | 5 | 11:04:46 | 1055.0 | 0 | -0.167 | 0.0966 | 52.7 |
16 | aci | 6 | 11:07:23 | 1211.5 | 0 | 5.240 | 0.1010 | 305.0 |
19 | aci | 7 | 11:09:43 | 1352.0 | 0 | 6.610 | 0.1040 | 284.0 |
22 | aci | 8 | 11:12:04 | 1492.5 | 0 | 9.280 | 0.1050 | 438.0 |
25 | aci | 9 | 11:14:24 | 1633.0 | 0 | 10.200 | 0.1020 | 616.0 |
28 | aci | 10 | 11:16:44 | 1772.5 | 0 | 10.500 | 0.0943 | 795.0 |
31 | aci | 11 | 11:19:49 | 1958.0 | 0 | 10.700 | 0.0853 | 970.0 |
34 | aci | 12 | 11:22:09 | 2097.5 | 0 | 11.100 | 0.0812 | 1150.0 |
41 | aq | 2 | 10:12:52 | 737.5 | 0 | 6.450 | 0.0700 | 239.0 |
44 | aq | 3 | 10:15:12 | 878.0 | 0 | 6.450 | 0.0684 | 235.0 |
47 | aq | 4 | 10:17:32 | 1017.5 | 0 | 5.960 | 0.0655 | 241.0 |
如果想另存为 csv 格式:
write.csv(df64, "./combined.csv")
header_line 表示你数据表头所在行,data_start 表示你数据起始行,Obs = 1 时所在行,不含表头。这个也要确认好了,不同的测量不能放在一起(当然一般不会出现这种情况,同一台仪器,处理数据当然是希望 aci 和 aci 在一起,lrc 和 lrc 在一起,调查测量和调查测量在一起),不同的测量可能起始行不同,这样就会报错,特别需要注意的是,目前路径写法仅支持 “/” 分隔,不能使用 “\“ 作为分隔。例如在数据放在 D 盘的 6400 文件夹下,那么写法应为”d:/6400”, 不能为 “d:\6400”, 尽管后者对 R 是合法的,主要是因为我要区分你不同数据来源的文件是哪个,也即下文提到的 df$files
列。
其中,数据的来源在表格中第一列,叫做 files,是数据来源的文件名(即你起的名字),例如本例中你看到的 aci 是我之前数据里面 aci 响应曲线的数据。
这些数据可以用于后文相关的分析中,尤其是像 fitacis
这样的函数,因为本质上他们都是符合 tidyverse
样式的数据。
2.2.2 LI-6400 数据重计算
参数的重计算函数为 recomp_6400
, 其参数除了 read_bat_6400
所包含的参数外,还有叶面积 S, 以及叶片正反面的气孔比例,默认值分别为 6 和 0.5。
library(readphoto)
<- read_bat_6400("./data/6400")
x1 <- recomp_6400("./data/6400", header_line = 17, data_start = 27, S = 6, K = 0.5)
y1
$Photo - y1$Photo x1
## [1] -0.0008873753 0.0026900500 -0.0012036469 0.0003483414 0.0006122641
## [6] -0.0113872639 -0.0020986076 0.0004962787 0.0188727482 -0.0294595908
## [11] -0.0436611445 -0.0339083408 0.0046772165 0.0036653298 0.0030397988
## [16] -0.0105901673 0.0040624956 0.0017317049 -0.0073252290 0.0054977377
## [21] 0.0039736503 0.0021704065 0.0046772165 0.0036653298 0.0030397988
## [26] -0.0105901673 0.0040624956 0.0017317049 -0.0073252290 0.0054977377
## [31] 0.0039736503 0.0021704065
$Trmmol - y1$Trmmol x1
## [1] -2.998596e-04 1.407338e-04 3.189451e-05 -4.586467e-04 -3.836822e-04
## [6] 5.402725e-04 -2.344852e-04 -7.684772e-05 5.979599e-04 -6.534341e-04
## [11] -6.779145e-04 2.469749e-04 3.812201e-04 2.313957e-04 3.508312e-04
## [16] -2.794358e-04 -5.406530e-04 5.230606e-04 -9.183370e-04 7.638850e-04
## [21] -2.578893e-04 2.203045e-04 3.812201e-04 2.313957e-04 3.508312e-04
## [26] -2.794358e-04 -5.406530e-04 5.230606e-04 -9.183370e-04 7.638850e-04
## [31] -2.578893e-04 2.203045e-04
$Cond - y1$Cond x1
## [1] -1.974217e-04 -3.594216e-04 -3.779119e-04 -3.806675e-04 -3.201411e-04
## [6] -1.483324e-04 -7.803345e-04 -2.671018e-04 1.028977e-04 -3.966192e-04
## [11] -3.190769e-04 -2.314266e-04 -2.746300e-04 1.094050e-05 -4.584791e-05
## [16] -1.084094e-04 -1.827768e-04 -1.344969e-04 -1.714096e-04 -8.180257e-05
## [21] -4.687906e-05 -1.000424e-04 -2.746300e-04 1.094050e-05 -4.584791e-05
## [26] -1.084094e-04 -1.827768e-04 -1.344969e-04 -1.714096e-04 -8.180257e-05
## [31] -4.687906e-05 -1.000424e-04
$Ci-y1$Ci x1
## [1] 0.434643936 -0.297820404 -0.308200950 -0.007847373 -0.035490198
## [6] 0.433706824 -0.416734067 -0.052089770 0.147655545 -0.315797917
## [11] -0.271335987 -0.228968795 0.356519198 0.311487646 0.052196075
## [16] 0.557128947 0.058563406 0.300198435 0.052607786 0.339000061
## [21] -0.252622980 -0.494554616 0.356519198 0.311487646 0.052196075
## [26] 0.557128947 0.058563406 0.300198435 0.052607786 0.339000061
## [31] -0.252622980 -0.494554616
# half of original the area
<- recomp_6400("./data/6400", header_line = 17, data_start = 27, S = 3, K = 0.5)
y1 $Photo/x1$Photo y1
## [1] 2.000254 1.998957 2.000767 1.999234 2.007333 2.004346 2.000635 1.999893
## [9] 1.996299 2.005611 2.008161 2.006110 1.998550 1.998863 1.998980 2.003671
## [17] 1.998391 1.999240 2.003866 1.995584 1.994199 2.010360 1.998550 1.998863
## [25] 1.998980 2.003671 1.998391 1.999240 2.003866 1.995584 1.994199 2.010360
# test with random area less than six
<- 6 - runif(32, 1, 3)
area <- recomp_6400("./data/6400", header_line = 17, data_start = 27, S = area, K = 0.5)
y1 $Photo/x1$Photo y1
## [1] 1.890741 1.442401 1.922837 1.460636 1.263409 1.414596 1.757261 1.521830
## [9] 1.291741 1.581095 1.452796 1.398753 1.884053 1.437109 1.228692 1.745059
## [17] 1.651811 1.603419 1.203926 1.310704 1.822923 1.804928 1.470240 1.768144
## [25] 1.900306 1.882726 1.906420 1.620766 1.682811 1.289687 1.447063 1.381292
我们看到各个值之差非常小,因为我们使用的是相同的叶面积,理论上这两次读数的差异应为 0, 但在实际计算过程中,有小数点位数的影响,所以某些值不完全为 0,但该差值足够小。我们将所有的数据叶面积减半后,二者比值也约等于 2.
2.3 LI-6800 数据的处理 {#6800data}
LI-6800 的数据我们可以直接处理 Excel 即可,读取我这里有两种方案,一种是 R
读取方案,一种是 python
读取方案,之所以这么复杂,是因为 LI-6800 的 Excel 格式较为复杂,不被常用的软件包所支持。我们分开来看两种方式:
2.3.1 R 下 Excel 格式读取的重计算 {##6800xlconnect}
偶然发现了 XLConnect
软件包的一个功能(以前知道这个软件包,但忽视了),那就是直接读取 LI-6800 Excel 格式的数据并重计算,我将其写成了函数,放在了我的 readphoto 软件包里,软件包的安装:
::install_github("zhujiedong/readphoto") remotes
当然,最近连我自己安装 github 的软件包都经常出问题,如果大家同样遇到问题,可以按照下面的方式安装:
::install_git("https://gitee.com/zhu_jie_dong/readphoto") remotes
其中:
path 是 Excel 文件的路径;
start_row 是数据开始的行号;
S 为修改的叶面积,默认值为 6,如果叶面积无需更改,则使用默认的 NULL。如果使用 aperture 更改了面积,且叶片能够充满叶室,比方说是 2 \(cm^2\),该值必须输入一个长度和测量值数量完全一致的向量,例如有 3 个测量值,我们输入 S 的长度则为 3,例如,一共有三个测量值,只有第一个叶片没充满叶室,面积为 1.5,其他的为 2,则输入方式为 S = c(1.5, 2, 2)。
我们直接使用下面的例子解释,导入的数据是 6 cm2 的默认面积:
library(readphoto)
<- xlconnect_read("./data/aci-xlc.xlsx")
df6 $A df6
## [1] 24.7381184 18.1379358 10.8055345 3.0239340 -0.9144044 26.9519572
## [7] 27.5088717 40.9101889 50.1393342 55.3865984 58.0662751 59.3556428
<- xlconnect_read("./data/aci-xlc.xlsx", S = rep(3, 12))
df3 $A/df3$A df6
## [1] 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5 0.5
<- xlconnect_read("./data/aci-xlc.xlsx", S = rnorm(12, 3, 0.1))
df_random $A/df_random$A df6
## [1] 0.4703268 0.5052066 0.5075169 0.5063254 0.5166228 0.4393696 0.4790926
## [8] 0.5081278 0.5143876 0.4945837 0.5079758 0.4884164
光合速率的倍数的变化在预期之内。
2.3.3 批量处理 csv 文件
如果还是比习惯用 R
,我们来处理上面的 csv
文件即可。其实没什么特别的,就是需要批量导入后添加一个分组标签即可。以下为示例:
<- list.files("./data/csvdata", full.names = TRUE)
files_csv files_csv
## [1] "./data/csvdata/racirtest1.csv" "./data/csvdata/rcirtest3.csv"
<- function(path){
add_remark <- read.csv(path)
df $remarks <- gsub(".csv", "", basename(path))
dfreturn(df)
}
<- lapply(files_csv, add_remark)
list_csv
<- do.call(rbind, list_csv)
df_remark
<- ncol(df_remark)
n head(df_remark[,(n-3):n])
## H2O_r_sp SS_s SS_r remarks
## 1 20 96.8399 99.4131 racirtest1
## 2 20 96.8405 99.4111 racirtest1
## 3 20 96.8409 99.4112 racirtest1
## 4 20 96.8411 99.4125 racirtest1
## 5 20 96.8413 99.4125 racirtest1
## 6 20 96.8411 99.4118 racirtest1
tail(df_remark[,(n-3):n])
## H2O_r_sp SS_s SS_r remarks
## 443 20 97.0539 99.6148 rcirtest3
## 444 20 97.0531 99.6159 rcirtest3
## 445 20 97.0533 99.6146 rcirtest3
## 446 20 97.0527 99.6133 rcirtest3
## 447 20 97.0534 99.6146 rcirtest3
## 448 20 97.0527 99.6146 rcirtest3
到此为止已经整理为所谓的 tidy data
了,用 tidyverse
也好,用 base
语法也好,总之是比较容易处理的数据了,例如上面其实是 RACiR
数据了,有两个,那么当然可以使用 plantecophys::fitacis
来一条命令搞定所有数据的拟合了。
这里需要注意的是使用 xlconnect_read
也可以使用类似的操作,但我觉得不如这种方法省事,故而只列出来这一种,有需要的也可以按照类似方法处理即可。