9  数据采集方法

10 数据采集方法

数据是生态学研究的核心。但”有数据”和”有好数据”是两回事。很多研究结论站不住脚,不是因为分析方法错了,而是因为数据采集从一开始就存在系统性问题。

这一章,我们系统学习生态学中获取数据的四大类方法:观测、实验、模型、公共数据。

10.1 数据来源四大类型

生态学研究中的数据,按来源可以分为四大类:

类型 是否干预 因果推断能力 数据成本 适用场景
观测数据 弱(关联) 中-高 探索性研究
实验数据 强(因果) 验证性研究
模型数据 虚拟 理论性 预测性研究
公共数据 弱(关联) 低-免费 整合分析

10.2 观测数据:自然的镜子

10.2.1 什么是观测数据?

观测数据是在自然状态下对研究对象进行系统性记录而获得的数据,研究者不施加任何干预。

优势:反映真实自然状态;可覆盖大时空尺度;是提出科学假设的主要途径。

局限:难以控制混杂变量;只能建立相关性;采样设计不当易产生系统性偏差。

10.2.2 观测数据的四大类型

1. 调查数据(Survey Data):问卷、访谈、焦点小组等方式收集的社会生态数据。

library(tidyverse)
set.seed(42)
survey_data <- tibble(
  household_id = 1:60,
  village = sample(c("村A", "村B", "村C", "村D"), 60, replace = TRUE),
  elevation_zone = sample(c("高海拔", "中海拔", "低海拔"), 60, replace = TRUE),
  land_area_ha = round(rnorm(60, 2.5, 0.8), 2),
  forest_cover_pct = round(rnorm(60, 45, 15), 1),
  fertilizer_kg_ha = round(rnorm(60, 180, 45), 0),
  annual_income_yuan = round(rnorm(60, 35000, 8000), 0)
)

survey_summary <- survey_data |>
  group_by(village, elevation_zone) |>
  summarise(n_households = n(), mean_land = mean(land_area_ha),
            mean_forest = mean(forest_cover_pct), .groups = "drop")
print(survey_summary)

2. 野外观测数据(Field Observation Data):直接在野外记录的生物和环境数据,是生态学研究的核心。

set.seed(2027)
field_data <- tibble(
  plot_id = paste0("P", sprintf("%02d", 1:24)),
  latitude = round(22.75 + rnorm(24, 0, 0.01), 6),
  longitude = round(108.32 + rnorm(24, 0, 0.01), 6),
  elevation = round(120 + rnorm(24, 0, 20), 0),
  canopy_cover_pct = round(rnorm(24, 75, 10), 1),
  species_richness = sample(8:25, 24, replace = TRUE),
  soil_depth_cm = sample(c(30, 40, 50, 60), 24, replace = TRUE),
  soil_moisture_pct = round(rnorm(24, 28, 5), 1),
  soil_pH = round(rnorm(24, 4.8, 0.3), 2),
  organic_carbon_g_kg = round(rnorm(24, 25, 6), 1),
  fire_history = sample(c("无", "1-2次", "3次以上"), 24, replace = TRUE,
                       prob = c(0.5, 0.3, 0.2)),
  grazing_intensity = sample(c("无", "轻度", "重度"), 24, replace = TRUE)
)
glimpse(field_data)

3. 遥感数据(Remote Sensing Data):卫星、无人机等平台获取的地表影像数据。

平台 空间分辨率 重访周期 免费 适合应用
Landsat 8/9 30m 16天 土地覆盖、植被指数
Sentinel-2 10m 5天 植被健康、精细监测
MODIS 250m-1km 每日 全球植被动态
无人机 厘米级 按需 自有 样地精细调查
library(lubridate)
set.seed(2027)
ndvi_ts <- tibble(
  date = seq(ymd("2020-01-01"), ymd("2023-12-31"), by = "month"),
  ndvi = 0.45 + 0.25 * sin(2 * pi * (as.numeric(format(date, "%j")) - 60) / 365) +
         rnorm(length(date), 0, 0.03)
)
ndvi_annual <- ndvi_ts |> mutate(year = year(date)) |>
  group_by(year) |> summarise(mean_ndvi = mean(ndvi), .groups = "drop")
print(ndvi_annual)
ggplot(ndvi_ts, aes(x = date, y = ndvi)) +
  geom_line(color = "darkgreen") + geom_point() +
  labs(x = "日期", y = "NDVI", title = "NDVI 时间序列 (2020-2023)") +
  theme_minimal()

4. 传感器数据(Sensor Data):自动监测设备连续记录的环境数据。

常见类型:气象站(温度、湿度、降水)、土壤水分传感器(TDR)、水质监测仪、CO2通量塔、相机陷阱。

set.seed(2027)
weather_station <- tibble(
  datetime = seq(ymd_hms("2024-07-01 00:00:00"), ymd_hms("2024-07-07 23:00:00"), by = "hour"),
  temp_c = 28 + 6 * sin(2 * pi * (hour(datetime) - 6) / 24) + rnorm(length(datetime), 0, 1.5),
  rh_pct = pmin(100, pmax(0, 75 - 0.8 * (temp_c - 28) + rnorm(length(datetime), 0, 5))),
  rainfall_mm = rpois(length(datetime), lambda = 0.1)
)
daily_summary <- weather_station |> mutate(date = as.Date(datetime)) |>
  group_by(date) |> summarise(mean_temp = mean(temp_c), total_rain = sum(rainfall_mm), .groups = "drop")
print(daily_summary)

10.3 实验数据:因果推断的利器

10.3.1 什么是实验数据?

实验数据是通过主动操纵一个或多个自变量(处理),观察因变量响应而获得的数据。实验是检验因果关系假设最有力的方法。

观测研究和实验研究的根本区别:观测研究只能建立相关性;实验研究通过随机分配处理,可以建立因果关系。

10.3.2 实验设计的四大原则

1. 随机化(Randomization):将实验单元随机分配到不同处理组,消除所有已知和未知的系统性偏差。

2. 重复(Replication):每个处理设置多个重复,提高统计检验力,并允许估计随机变异。

3. 对照(Control):设置对照组作为基线参考。

4. 区组化(Blocking):将实验单元按已知会影响响应的特征分组(分块),然后在每个块内随机分配处理。

10.3.3 五种常见的实验设计

设计一:完全随机设计(CRD)

最简单的设计,所有实验单元完全随机分配到各处理组。适用场景:实验条件高度均一。

library(tidyverse)
set.seed(2027)
crd_data <- tibble(
  pot_id = 1:36,
  treatment = sample(rep(c("对照", "低氮", "中氮", "高氮"), each = 9)),
  nitrogen_rate = case_when(treatment == "对照" ~ 0, treatment == "低氮" ~ 50,
                           treatment == "中氮" ~ 100, treatment == "高氮" ~ 200),
  biomass_g = case_when(treatment == "对照" ~ rnorm(9, mean = 85, sd = 12),
                        treatment == "低氮" ~ rnorm(9, mean = 105, sd = 12),
                        treatment == "中氮" ~ rnorm(9, mean = 120, sd = 12),
                        treatment == "高氮" ~ rnorm(9, mean = 115, sd = 12)),
  leaf_n_pct = case_when(treatment == "对照" ~ rnorm(9, mean = 1.8, sd = 0.2),
                         treatment == "低氮" ~ rnorm(9, mean = 2.3, sd = 0.2),
                         treatment == "中氮" ~ rnorm(9, mean = 2.8, sd = 0.2),
                         treatment == "高氮" ~ rnorm(9, mean = 3.3, sd = 0.2))
)
ggplot(crd_data, aes(x = treatment, y = biomass_g, fill = treatment)) +
  geom_boxplot(alpha = 0.7, outlier.shape = NA) +
  geom_jitter(width = 0.25, alpha = 0.6, size = 2) +
  stat_summary(fun = mean, geom = "point", color = "red", size = 3, shape = 3) +
  labs(x = "氮肥处理", y = "植物生物量 (g)",
       title = "完全随机设计:氮肥对植物生物量的影响") +
  theme_minimal() + theme(legend.position = "none")
aov_result <- aov(biomass_g ~ treatment, data = crd_data)
summary(aov_result)
TukeyHSD(aov_result)

设计二:随机区组设计(RCBD)

将实验单元按某种特征分成若干区组,每个区组内包含所有处理的随机排列。适用场景:野外实验、温室实验(不同架子间有差异)。

set.seed(2027)
rcbd_data <- expand_grid(
  block = c("上坡", "中坡", "下坡"),
  treatment = c("对照", "有机肥", "化肥", "有机+化肥")
) |>
  mutate(
    plot_id = paste0(block, "-", row_number()),
    block_effect = case_when(block == "上坡" ~ -5, block == "中坡" ~ 0, block == "下坡" ~ 7),
    treatment_effect = case_when(treatment == "对照" ~ 0, treatment == "有机肥" ~ 9,
                                treatment == "化肥" ~ 3, treatment == "有机+化肥" ~ 12),
    som_g_kg = 18 + block_effect + treatment_effect + rnorm(n(), 0, 2),
    som_g_kg = pmax(10, som_g_kg)
  )
ggplot(rcbd_data, aes(x = treatment, y = som_g_kg, fill = block)) +
  geom_boxplot(alpha = 0.7) +
  labs(x = "施肥处理", y = "土壤有机质 (g/kg)",
       title = "随机区组设计:坡位和施肥对土壤有机质的影响", fill = "区组(坡位)") +
  theme_minimal() + theme(axis.text.x = element_text(angle = 15, hjust = 1))
aov_rcbd <- aov(som_g_kg ~ block + treatment, data = rcbd_data)
summary(aov_rcbd)

设计三:裂区设计(Split-Plot Design)

当实验包含两个层次的实验单元时使用。主区因素难以随机化(如灌溉),副区因素可以在主区内随机分配。适用场景:农业实验、森林间伐实验。

set.seed(2027)
split_plot <- expand_grid(
  block = 1:3,
  irrigation = c("充分灌溉", "适度干旱"),
  species = c("马尾松", "红锥", "红椎")
) |>
  mutate(
    irr_effect = case_when(irrigation == "充分灌溉" ~ 0, irrigation == "适度干旱" ~ -250),
    species_effect = case_when(species == "马尾松" ~ 0, species == "红锥" ~ 350, species == "红椎" ~ 280),
    interaction = if_else(irrigation == "适度干旱" & species == "红锥", 150,
                          if_else(irrigation == "适度干旱" & species == "红椎", 120, 0)),
    height_cm = 180 + irr_effect + species_effect + interaction + rnorm(n(), 0, 50),
    height_cm = pmax(50, height_cm)
  )
ggplot(split_plot, aes(x = irrigation, y = height_cm, color = species, group = species)) +
  stat_summary(fun = mean, geom = "line", linewidth = 1.2) +
  stat_summary(fun = mean, geom = "point", size = 3) +
  stat_summary(fun.data = mean_se, geom = "errorbar", width = 0.15) +
  labs(x = "灌溉处理", y = "树高年增长量 (cm)",
       title = "裂区设计:灌溉与树种的交互效应", color = "树种") +
  theme_minimal()

设计四:因子设计(Factorial Design)

同时研究两个或多个因素的效应,以及交互效应。

set.seed(2027)
factorial_data <- expand_grid(
  N_level = c("不施氮", "低氮", "高氮"),
  P_level = c("不施磷", "施磷")
) |>
  mutate(
    n_effect = case_when(N_level == "不施氮" ~ 0, N_level == "低氮" ~ 25, N_level == "高氮" ~ 45),
    p_effect = if_else(P_level == "施磷", 18, 0),
    np_interaction = if_else(N_level != "不施氮" & P_level == "施磷", 12, 0),
    biomass_g = 90 + n_effect + p_effect + np_interaction + rnorm(n(), 0, 10),
    biomass_g = pmax(50, biomass_g)
  )
ggplot(factorial_data, aes(x = N_level, y = biomass_g, fill = P_level)) +
  stat_summary(fun = mean, geom = "bar", position = "dodge", alpha = 0.7) +
  stat_summary(fun.data = mean_se, geom = "errorbar", position = position_dodge(0.9), width = 0.3) +
  labs(x = "氮添加水平", y = "植物生物量 (g)",
       title = "两因素因子设计:氮×磷交互效应", fill = "磷添加") +
  theme_minimal() + theme(axis.text.x = element_text(angle = 15, hjust = 1))

设计五:嵌套设计(Nested Design)

当抽样单元嵌套在更大的单元内部时使用。适用场景:多尺度生态过程研究。

set.seed(2027)
nested_data <- expand_grid(
  reserve = c("保护区A", "保护区B", "保护区C"),
  plot = 1:3,
  quadrat = 1:5
) |>
  mutate(
    quadrat_id = paste0(reserve, "-P", plot, "-Q", quadrat),
    reserve_effect = case_when(reserve == "保护区A" ~ 0, reserve == "保护区B" ~ 3, reserve == "保护区C" ~ 8),
    plot_effect = rnorm(45, 0, 1.5),
    shannon_index = 2.5 + reserve_effect + plot_effect + rnorm(45, 0, 0.3),
    shannon_index = pmax(1, shannon_index)
  )
nested_summary <- nested_data |> group_by(reserve) |>
  summarise(mean_shannon = mean(shannon_index), se_shannon = sd(shannon_index) / sqrt(n()), .groups = "drop")
ggplot(nested_summary, aes(x = reserve, y = mean_shannon)) +
  geom_col(fill = "steelblue", alpha = 0.7) +
  geom_errorbar(aes(ymin = mean_shannon - se_shannon, ymax = mean_shannon + se_shannon), width = 0.3) +
  labs(x = "保护区", y = "平均Shannon指数", title = "嵌套设计:不同保护区的物种多样性") +
  theme_minimal()

10.4 采样设计:科学抽样的核心

10.4.1 核心概念

  • 总体(Population):你想研究的全部个体或单元的集合。
  • 样本(Sample):从总体中实际采集数据的单元子集。
  • 抽样框(Sampling Frame):列出所有抽样单元的名录或地图。
  • 抽样误差:因样本无法完全代表总体而产生,可控制但不可避免。
  • 非抽样误差:由测量错误、记录错误、缺失数据等引起,应尽量避免。

10.4.2 常用抽样方法

方法 原理 优点 缺点 适用场景
简单随机抽样 每个单元等概率被选 统计推断简单 效率低,可能聚集 总体均匀、样本量充足
系统抽样 按固定间隔选取 简单易行、分布均匀 可能有隐藏周期 空间变异均匀
分层抽样 先分层再各层随机抽 提高精度、控制组间差异 需要先验分层信息 组间差异明显
整群抽样 随机选群,整群调查 节省成本 群内相似性高则精度低 地理分散总体
嵌套抽样 多尺度嵌套调查 可同时分析多尺度效应 设计与分析复杂 多尺度生态过程

10.4.3 样本量估算

样本量不是拍脑袋定的,需要基于统计原理计算:

library(pwr)

# 比较两组均值,检测中等效应量 d = 0.5
pwr.t.test(d = 0.5, sig.level = 0.05, power = 0.80, type = "two.sample")
# 结果:每组需要 n = 64

# 检测相关系数 r = 0.3
pwr.r.test(r = 0.3, sig.level = 0.05, power = 0.80)
# 结果:需要 n = 85

# 多组比较(ANOVA),k = 4 组,f = 0.25
pwr.anova.test(k = 4, f = 0.25, sig.level = 0.05, power = 0.80)
# 结果:每组需要 n = 52

10.4.4 空间自相关与采样设计

空间自相关(Spatial Autocorrelation):相邻样本点不独立,彼此相似。

后果:违反统计假设;导致有效样本量远小于名义样本量;传统统计检验容易犯 Type I 错误(假阳性)。

library(gstat)
library(sp)

set.seed(2027)
spatial_data <- tibble(
  x = runif(50, 0, 100), y = runif(50, 0, 100),
  soc = 25 + 0.3 * x + 0.2 * y + rnorm(50, 0, 3),
  soc = pmax(10, soc)
)
coordinates(spatial_data) <- ~x + y
variogram_model <- variogram(soc ~ 1, data = spatial_data, cutoff = 40)
plot(variogram_model)
# 距离接近0时变异接近0 = 存在空间自相关

10.5 生态学专项采样方法

10.5.1 植物群落调查:样方法

样方法是最经典的植物群落调查方法,通过在样地中设置固定面积的样方来调查植物组成。

set.seed(2027)
quadrat_data <- tibble(
  quadrat_id = paste0("Q", sprintf("%03d", 1:20)),
  distance_from_edge = round(runif(20, 2, 48), 1),
  species_count = sample(5:15, 20, replace = TRUE),
  total_cover_pct = round(pmin(100, rnorm(20, 85, 12)), 0),
  dominant_species = sample(c("马尾松", "红锥", "荷木", "椎木", "芒萁"), 20, replace = TRUE),
  slope_pct = round(rnorm(20, 20, 8), 1),
  rock_cover_pct = pmax(0, round(rnorm(20, 15, 10), 0))
)
print(quadrat_data, width = Inf)

10.5.2 动物调查:标记重捕法

标记重捕法是估计动物种群数量的经典方法。

M <- 30  # 第一次捕获并标记的个体数
C <- 25  # 第二次捕获的个体总数
R <- 8   # 第二次捕获中带标记的个体数

N_hat <- (M * C) / R
cat("估计的种群大小:", round(N_hat), "只\n")
var_N <- (M^2 * C * (C - R)) / (R^3)
se_N <- sqrt(var_N)
cat("标准误:", round(se_N), "只\n")
cat("95% CI:", round(N_hat - 1.96 * se_N), "~", round(N_hat + 1.96 * se_N), "只\n")

# Chapman 修正(对小样本更准确)
N_chapman <- ((M + 1) * (C + 1)) / (R + 1)
cat("Chapman修正估计:", round(N_chapman), "只\n")

10.5.3 相机陷阱法

相机陷阱是调查哺乳动物多样性的自动化工具。

set.seed(2027)
camera_data <- tibble(
  camera_id = paste0("CAM", sprintf("%02d", 1:15)),
  deployment_date = seq(ymd("2024-01-01"), by = "month", length.out = 15),
  latitude = round(22.75 + rnorm(15, 0, 0.02), 6),
  longitude = round(108.32 + rnorm(15, 0, 0.02), 6),
  n_independent_events = sample(3:25, 15, replace = TRUE),
  dominant_species = sample(c("野猪", "小麂", "赤麂", "果子狸", "豹猫"), 15, replace = TRUE),
  camera_days = sample(30:90, 15, replace = TRUE)
) |>
  mutate(detection_rate = round(n_independent_events / camera_days, 3))
print(camera_data)

10.6 数据采集的质量控制

10.6.1 质量控制的核心措施

1. 标准化测量程序

在采样前制定详细的操作规程(Standard Operating Procedure, SOP),确保所有人使用相同的测量方法。关键要素:测量顺序、读数方法、异常值判定标准、记录格式。

2. 仪器校准

定期校准测量仪器,记录校准信息。

calibration_log <- tibble(
  instrument_id = "TDR-300-SM",
  calibration_date = ymd(c("2024-03-01", "2024-04-01", "2024-05-01")),
  standard_value = c(25.0, 25.0, 25.0),
  measured_value = c(25.3, 24.8, 25.1),
  correction_factor = standard_value / measured_value,
  technician = c("张三", "李四", "王五")
)
print(calibration_log)

3. 盲法测量

测量人员不知道处理分组,避免主观偏差。

4. 重复测量

对关键指标进行技术重复,评估测量误差。

set.seed(2027)
repeat_measurements <- tibble(
  sample_id = rep(paste0("S", sprintf("%02d", 1:10)), each = 3),
  observer = rep(c("张三", "李四", "王五"), 10),
  measured_value = round(rnorm(30, 50, 5), 2),
  true_value = rep(seq(45, 54, length.out = 10), each = 3)
) |>
  mutate(error = measured_value - true_value)

measurement_bias <- repeat_measurements |>
  group_by(observer) |>
  summarise(mean_error = mean(error), sd_error = sd(error), max_error = max(abs(error)), .groups = "drop")
print(measurement_bias)

5. 现场数据检查

在采样现场进行初步的数据检查,及时发现和纠正问题。

field_qc <- function(data) {
  range_check <- data |>
    mutate(ph_out_of_range = soil_pH < 3 | soil_pH > 10,
           moisture_out_of_range = soil_moisture_pct < 0 | soil_moisture_pct > 100)
  cat("pH超范围记录:", sum(range_check$ph_out_of_range), "条\n")
  cat("含水量超范围记录:", sum(range_check$moisture_out_of_range), "条\n")
}
field_qc(field_data)

10.7 常见错误与规避

10.7.1 错误一:选择性采样

便利采样(只采容易获取的样本)、自愿响应偏差、存活者偏差。规避:严格按照预定采样设计执行,使用随机或系统抽样。

10.7.2 错误二:测量尺度不一致

不同时间或不同仪器使用不同精度,导致数据不可比。规避:制定统一的数据字典,明确每个变量的定义和测量方法。

10.7.3 错误三:缺失数据非随机

缺失与未观测值系统性相关(如干旱年份因土壤过硬无法采样)。规避:记录每个样本的采集状态,详细记录缺失原因。

10.7.4 错误四:空间采样偏差

忽视边缘效应,在样地边界的样本不代表整体。规避:设计采样时间表时考虑生态节律,使用空间分层抽样。

10.7.5 错误五:变量定义模糊

不同采集者对同一现象给出不同记录(如”灌木盖度”定义不清)。规避:采集前制定详尽的数据字典。

10.8 课后练习

10.8.1 基础题

练习 1:判断数据类型

以下研究问题涉及哪些数据类型?属于观测、实验、模型还是公共数据?

  1. 使用 WorldClim 气候数据库提取研究地点的年均温数据
  2. 在马尾松林中设置海拔梯度,测量土壤有机碳含量
  3. 利用 LiDAR 点云数据估算森林生物量
  4. 每月一次在固定样线上统计鸟类种类和个体数

练习 2:判断抽样方法

某研究想比较不同演替阶段的土壤微生物多样性,每种演替阶段各设 5 个样方,每个样方内用五点取样法采集土壤样本。

  1. 该设计使用了哪几种抽样方法?
  2. 这种设计是否属于分层抽样?为什么?
  3. 五点取样法属于系统抽样吗?

练习 3:识别采样偏差

某团队在城市公园调查土壤蚯蚓多样性,选择了周六下午3点在游客较多的中心区域采样,用手捡法收集蚯蚓。

分析:可能存在哪些选择性采样问题?如何改进?

10.8.2 应用题

练习 4:设计采样方案

假设你的研究课题是”氮沉降对亚热带人工林土壤酸化进程的影响”:

  1. 列出你的研究需要采集哪些变量
  2. 设计一个合理的采样方案(重复数、采样尺度、时间频率)
  3. 创建一个数据记录表模板
  4. 列出需要记录的元数据信息

练习 5:样本量估算

假设你想研究马尾松和红锥混交林中两种树的胸径(DBH)差异,预期效应量为 5cm(处理组均值约25cm,对照组约20cm),估计标准差约为8cm。在 α = 0.05 下达到 80% 统计功效。使用 R 中的 pwr 包计算每组需要的最小样本量,并讨论实际操作中应该增加多少重复数以应对样本损耗。

练习 6:标记重捕数据分析

某研究者在封闭池塘中进行标记重捕实验。第一次捕获并标记了 30 只虾,一周后第二次捕获了 25 只,其中 8 只带有标记。

请计算:a) Lincoln-Petersen 估计量;b) Chapman 修正估计量;c) 95% 置信区间。

10.8.3 思考题

练习 7:实验设计选择

如果你想研究以下生态学问题,应该选择哪种实验设计?为什么?

  1. 不同氮肥类型(有机肥 vs 化肥 vs 对照)对马尾松幼苗生长的影响,实验在温室进行,盆栽条件均一
  2. 不同坡位(上坡、中坡、下坡)对土壤有机碳的影响,同时想比较有机肥和化肥的效应
  3. 灌溉频率和树种对人工林生产力的影响,其中灌溉需要整个地块为单位处理,而树种可以在地块内随机分配
  4. 从保护区到人类干扰区的物种多样性梯度变化,每个保护区-干扰区作为一个研究单元

练习 8:评估你自己的研究数据

思考你当前的研究或课程项目:

  1. 你的研究数据是通过什么方式采集的?属于观测、实验还是模型数据?
  2. 采样设计是否合理?存在哪些潜在的采样偏差?
  3. 数据采集过程中是否有质量控制措施?
  4. 如果有机会重新设计采样方案,你会做哪些改进?