使用group_by函数计算鸟类行为频率时如何保留其他列?
解决方法
要在计算行为频率的同时保留性别、行为发生时间等列,你可以通过以下几种方式实现,核心思路是确保需要保留的列要么被包含在分组逻辑中,要么通过合并数据的方式补回:
方法一:分组时加入固定属性列
对于单只鸟来说,性别(sex)、个体ID这类属性是固定不变的,行为对应的rf8fitted标签通常也和behaviors一一对应,因此可以直接将这些列加入group_by,再通过summarise保留:
# 筛选单只鸟数据(用dplyr语法更统一) alm18subset <- df %>% filter(individualID == "Almen18 (eobs 5861)") # 计算频率并保留所需列 alm18freq <- alm18subset %>% # 加入需要保留的固定列到分组 group_by(agesincetaggingdays, behaviors, sex, rf8fitted, individualID) %>% summarise( n = n(), # 统计当日该行为的记录数 # 提取当日行为发生的时间(取当日第一条记录的时间为例) record_datetime = first(datetime), .groups = "drop" # 计算后取消分组 ) %>% # 按日期计算每种行为的频率 group_by(agesincetaggingdays) %>% mutate(freq = n / sum(n)) %>% ungroup() %>% # 筛选Active行为 filter(rf8fitted == "Active")
方法二:先算频率,再合并元数据
如果需要保留的列较多,或者不确定分组内是否唯一,可以先单独计算频率,再提取原数据中的元信息合并:
# 第一步:计算每日各行为的频率 freq_data <- alm18subset %>% group_by(agesincetaggingdays, behaviors) %>% summarise(n = n(), .groups = "drop") %>% group_by(agesincetaggingdays) %>% mutate(freq = n / sum(n)) %>% ungroup() # 第二步:提取需要保留的元数据(每个分组取唯一值) meta_data <- alm18subset %>% group_by(agesincetaggingdays, behaviors) %>% summarise( sex = first(sex), rf8fitted = first(rf8fitted), record_datetime = first(datetime), individualID = first(individualID), .groups = "drop" ) # 第三步:合并数据并筛选 alm18freq <- freq_data %>% left_join(meta_data, by = c("agesincetaggingdays", "behaviors")) %>% filter(rf8fitted == "Active")
方法三:用mutate计算频率并去重
如果需要保留所有原始列,可先通过mutate计算频率,再去重得到每日每种行为的唯一记录:
alm18freq <- alm18subset %>% # 先计算当日总记录数 group_by(agesincetaggingdays) %>% mutate(total_daily = n()) %>% ungroup() %>% # 计算每种行为的记录数和频率 group_by(agesincetaggingdays, behaviors) %>% mutate( n = n(), freq = n / first(total_daily) ) %>% ungroup() %>% # 去重,保留每日每种行为的唯一行 distinct(agesincetaggingdays, behaviors, sex, rf8fitted, record_datetime, n, freq, .keep_all = FALSE) %>% # 筛选Active行为 filter(rf8fitted == "Active")
注意事项
- 若
rf8fitted与behaviors并非一一对应,需调整分组逻辑或筛选时机,确保筛选的是正确的行为记录。 - 对于行为发生时间这类列,可根据需求选择
first()、last()或min()/max()提取当日的代表时间。
内容的提问来源于stack exchange,提问作者Skyk
相关产品推荐
相关产品推荐

