如何在R中按动物ID与小时对声学遥测数据框随机抽样?
问题描述
现有113,000余条声学遥测数据,需为每个唯一transmitter_id(动物ID)每小时随机抽取一条数据记录,部分transmitter_id并非每小时都有数据。数据示例如下:
data_hour transmitter_id DATETIME 1 2021-10-15 19:00 64617 2021-10-15 19:06:11 2 2021-10-15 19:00 64599 2021-10-15 19:07:08 3 2021-10-15 19:00 64599 2021-10-15 19:12:10 4 2021-10-15 19:00 64621 2021-10-15 19:16:29 5 2021-10-15 19:00 64599 2021-10-15 19:20:09 6 2021-10-15 19:00 64599 2021-10-15 19:21:47 .... 35 2021-10-15 19:00 64621 2021-10-15 19:58:09 36 2021-10-15 19:00 64617 2021-10-15 19:58:44 37 2021-10-15 19:00 64599 2021-10-15 19:59:41 38 2021-10-15 20:00 64599 2021-10-15 20:02:16 39 2021-10-15 20:00 64599 2021-10-15 20:04:20 40 2021-10-15 20:00 64617 2021-10-15 20:04:29 41 2021-10-15 20:00 64621 2021-10-15 20:05:15 42 2021-10-15 20:00 64617 2021-10-15 20:07:01 43 2021-10-15 20:00 64599 2021-10-15 20:07:25 44 2021-10-15 20:00 64603 2021-10-15 20:09:11 ...etc.
解决方案
方法一:使用tidyverse包(推荐,代码直观易读)
tidyverse中的dplyr包能高效实现分组抽样,步骤如下:
- 安装并加载tidyverse包(首次使用需安装):
install.packages("tidyverse") library(tidyverse)
- 分组抽样:
# 假设你的数据存储在名为df的数据框中 sampled_data <- df %>% group_by(transmitter_id, data_hour) %>% sample_n(size = 1) %>% ungroup()
group_by(transmitter_id, data_hour):按动物ID和小时维度分组,确保每个动物的每小时数据单独处理sample_n(size = 1):每组随机抽取1条记录ungroup():取消分组,转换为普通数据框格式
该方法会自动跳过无数据的动物-小时组合,无需额外处理。
方法二:使用基础R(无需额外安装包)
若不想安装新包,可通过基础R函数实现:
# 按动物ID和小时拆分数据 split_df <- split(df, list(df$transmitter_id, df$data_hour)) # 对每个子数据框随机选1条,过滤空组 sampled_list <- lapply(split_df, function(x) { if(nrow(x) > 0) x[sample(nrow(x), 1), ] }) # 合并结果为单个数据框 sampled_data <- do.call(rbind, sampled_list)
split():将原始数据拆分为多个子数据框,每个对应一个动物-小时组合lapply():遍历子数据框,有数据则随机选1条,无数据则跳过do.call(rbind, ...):将所有有效子数据框合并为最终结果
结果验证
可通过以下代码确认抽样是否符合要求:
# 统计每个动物每小时的记录数 sampled_data %>% count(transmitter_id, data_hour)
正常情况下,每个组合的计数均为1,无数据的组合不会出现在结果中。
内容的提问来源于stack exchange,提问作者fishlakeslimno
相关产品推荐
相关产品推荐

