R语言求助:500Hz转1Hz下采样并保留各ID首个数据值
解决皮肤温度数据下采样问题(保留每个ID首个数据)
听起来你遇到的核心问题是分组时间序列的下采样,还要兼顾小样本ID的处理,避免出现argument length 0的错误。我会给你两种可行的方案,都不需要caret包,分别适配不同的数据场景:
场景1:数据是严格均匀500Hz采样(无缺失、行号对应时间顺序)
这种情况我们可以直接按行号步长来采样,同时强制保留每个ID的第一行数据:
方案1:用dplyr(简洁直观)
假设你的数据框有id(分组ID)、temp(皮肤温度)、time(时间列,可选但推荐):
library(dplyr) df_downsampled <- df %>% # 先确保每个ID的数据按时间排序(如果没有time列,用row_number()替代) group_by(id) %>% arrange(id, time) %>% do({ # 提取当前ID的第一行 first_entry <- slice(., 1) # 从第501行开始,每500行取一个(对应1Hz采样) # 注意:如果当前ID的样本数≤500,sampled_rows会是空的,直接保留第一行即可 sampled_entries <- slice(., seq(from = 501, to = nrow(.), by = 500)) # 合并两部分数据 bind_rows(first_entry, sampled_entries) }) %>% ungroup()
方案2:用Base R(无需额外包)
如果不想加载dplyr,用原生R代码也能实现:
# 先按ID排序,保证分组连续性 df <- df[order(df$id), ] # 按ID拆分数据 id_groups <- split(df, df$id) # 逐个处理每个ID的分组 processed_groups <- lapply(id_groups, function(group) { first_row <- group[1, , drop = FALSE] # 只有当样本数超过500时,才进行下采样;否则直接保留第一行 if (nrow(group) > 500) { sampled_rows <- group[seq(501, nrow(group), 500), , drop = FALSE] rbind(first_row, sampled_rows) } else { first_row } }) # 合并处理后的分组,重置行名 df_downsampled <- do.call(rbind, processed_groups) rownames(df_downsampled) <- NULL
场景2:数据存在缺失/采样不严格均匀(有准确时间列)
如果你的数据有缺失值,或者时间不是严格按行号对应,建议用时间区间匹配的方式采样,更鲁棒:
library(dplyr) df_downsampled <- df %>% group_by(id) %>% arrange(id, time) %>% mutate( # 计算每个数据点相对于当前ID首个数据的时间差(单位:秒) time_since_first = time - first(time), # 把时间划分为每1秒一个区间,首个数据对应区间0 one_sec_interval = floor(time_since_first) ) %>% # 每个区间只保留第一个数据点(自然包含了ID的首个数据) distinct(id, one_sec_interval, .keep_all = TRUE) %>% ungroup() %>% # 可选:删除辅助列 select(-time_since_first, -one_sec_interval)
为什么你之前会遇到argument length 0错误?
大概率是因为某个ID的样本数不足500条,当你尝试用seq(from=501, to=nrow(group), by=500)时,生成的序列长度为0,导致提取行时出错。上面的两种方案都加入了对小样本ID的判断,完美规避了这个问题。
内容的提问来源于stack exchange,提问作者HCAI
相关产品推荐
相关产品推荐

