You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于时空事件数据集测算位置遍历性的R语言实现优化咨询

空间位置事件遍历性测算问题

我拥有一个记录多年(按年度统计)带空间坐标事件的数据集,希望测算位置随时间变化的遍历性(ergodicity),即事件在同一位置重复发生的程度(无需区分单位置的事件发生总量)。

为实现该目标,我选择统计多个累积时间区间内各位置的活跃年数(位置可在不连续的年份处于活跃状态),观测随着累积区间延伸至整个研究周期,不同活跃频次区间对应的位置数量变化规律。我在下方提供了玩具数据集示例,我的实际数据集规模更大、研究周期更长。

我想咨询现有实现逻辑是否合理,以及代码是否可以简化或优化。


初始实现代码

# 1990-1999共10年间60个点位发生的100条事件的玩具数据集
df1 <- structure(list(year = c("1997", "1996", "1998", "1995", "1997", "1995", "1995", "1997", "1997", "1999", "1997", "1999", "1996", "1997", "1997", "1991", "1996", "1992", "1993", "1999", "1997", "1995", "1997", "1996", "1997", "1997", "1991", "1997", "1997", "1998", "1999", "1996", "1997", "1998", "1996", "1998", "1997", "1999", "1999", "1995", "1998", "1996", "1996", "1997", "1995", "1996", "1995", "1995", "1994", "1997", "1998", "1999", "1999", "1999", "1995", "1999", "1999", "1999", "1999", "1997", "1999", "1994", "1994", "1996", "1994", "1999", "1999", "1993", "1997", "1999", "1999", "1998", "1999", "1998", "1999", "1997", "1999", "1996", "1996", "1996", "1999", "1996", "1995", "1995", "1997", "1996", "1999", "1999", "1997", "1994", "1995", "1995", "1999", "1996", "1998", "1997", "1997", "1995", "1999", "1998"), lng = c(127.107, 126.855, 126.896, 126.908, 126.951, 126.994, 126.833, 126.855, 126.939, 126.65, 127.01, 127.107, 126.864, 127.107, 126.65, 126.864, 126.951, 127.01, 127.139, 127.107, 127.492, 127.113, 127.119, 126.831, 127.009, 127.139, 127.047, 127.124, 126.732, 127.047, 126.908, 127.197, 126.903, 127.077, 126.951, 127.096, 126.972, 126.831, 127.047, 127.035, 126.85, 126.722, 126.932, 127.124, 126.872, 127.035, 127.069, 126.678, 127.124, 126.65, 126.887, 127.139, 127.047, 127.04, 126.855, 127.047, 127.01, 127.01, 126.841, 127.018, 126.937, 126.952, 127.047, 126.738, 126.831, 126.935, 126.871, 126.911, 126.707, 127.107, 126.972, 127.01, 126.937, 127.5, 126.968, 127.113, 127.035, 126.865, 126.831, 127.054, 127.035, 127.199, 126.722, 127.518, 126.98, 127.12, 126.972, 126.874, 126.965, 127.009, 127.518, 126.873, 126.722, 126.848, 127.009, 127, 127.113, 126.937, 127.107, 126.951), lat = c(37.5145, 37.5165, 37.5264, 37.5638, 37.3164, 37.4264, 37.5243, 37.5165, 37.5124, 37.4637, 37.3038, 37.5145, 37.4785, 37.5145, 37.4637, 37.4785, 37.3926, 37.3038, 37.434, 37.5145, 37.2298, 36.9921, 37.3827, 37.1995, 37.2911, 37.4449, 37.5172, 37.5301, 37.447, 37.5172, 37.5638, 37.5384, 37.5683, 37.1498, 37.3926, 37.5256, 37.2572, 37.3219, 37.6688, 37.2861, 37.551, 37.507, 37.3865, 37.5301, 37.4793, 37.2861, 37.205, 37.4094, 37.5301, 37.4637, 37.4954, 37.434, 37.5172, 37.5744, 37.5165, 37.5172, 37.3038, 37.3038, 37.2876, 37.5891, 37.5791, 37.4784, 37.5172, 37.5369, 37.3219, 37.3617, 37.3117, 37.388, 37.35, 37.5145, 37.2572, 37.3038, 37.5791, 37.2642, 37.3447, 36.9921, 37.2861, 37.2913, 37.3219, 37.5819, 37.2861, 37.6977, 37.507, 37.4138, 37.2965, 37.3004, 37.2572, 37.3618, 37.5384, 37.2911, 37.4138, 37.4612, 37.507, 37.534, 37.2911, 37.45, 36.9921, 37.5791, 37.5145, 37.3926)), row.names = c(NA, -100L), class = c("data.table", "data.frame"))

library(dplyr)
library(tidyr) #用于unite函数

#交叉统计年份与唯一位置的对应关系
df2 <- df1 %>% distinct(year,lng,lat) %>% unite(coord, c("lng", "lat"), sep=";")
df2 <- table(df2$coord, df2$year) %>% t %>% as.data.frame(stringsAsFactors=F)
colnames(df2) <- c("year", "coord", "freq")

#测算遍历性:按2年区间分箱,统计当前及之前区间内的活跃年数,首先统计1-2年活跃频次的位置数
df2 %>% filter(year<1992 & freq!=0) %>% group_by(coord) %>% mutate(freq=sum(freq)) %>% 
  filter(freq<3) %>% distinct(coord) %>% nrow
#[1] 2 (1990-1991区间内共有2个不同位置活跃了1或2年)
df2 %>% filter(year<1994 & freq!=0) %>% group_by(coord) %>% mutate(freq=sum(freq)) %>% 
  filter(freq<3) %>% distinct(coord) %>% nrow
#[1] 5 (1990-1993区间内共有5个不同位置活跃了1或2年)
df2 %>% filter(year<1996 & freq!=0) %>% group_by(coord) %>% mutate(freq=sum(freq)) %>% 
  filter(freq<3) %>% distinct(coord) %>% nrow
#[1] 22
df2 %>% filter(year<1998 & freq!=0) %>% group_by(coord) %>% mutate(freq=sum(freq)) %>% 
  filter(freq<3) %>% distinct(coord) %>% nrow
#[1] 46
df2 %>% filter(year<2000 & freq!=0) %>% group_by(coord) %>% mutate(freq=sum(freq)) %>% 
  filter(freq<3) %>% distinct(coord) %>% nrow
#[1] 53

完成1-2年活跃频次的统计后,我会继续统计3-4年等更高的频次区间,直至覆盖整个10年研究周期。按照逻辑设计,2年的初始累积区间内不会出现活跃3-4年的位置,我期望最终输出以频次区间为行、累积时间区间为列、单元格为对应位置数量的统计表格。

嵌套循环实现版本

#测算遍历性:按2年区间分箱,统计当前及之前区间内的活跃年数
df3 <- matrix(ncol=5, nrow=5) #构建输出矩阵
colnames(df3) <- paste0(1990, "-", 1990+2*1:5-1) #累积区间
rownames(df3) <- paste0(2*(1:5-1)+1, "-", 2*1:5, " years") #频次区间
for (i in 1:5) {
  for (j in 1:5) {
  df3[i,j] <- df2 %>% filter(year<=1990+2*j-1 & freq!=0) %>% group_by(coord) %>% 
    mutate(freq=sum(freq)) %>% filter(freq>=2*(i-1)+1 & freq<=2*i) %>% distinct(coord) %>% 
    nrow
  }
}

df3
#            1990-1991 1990-1993 1990-1995 1990-1997 1990-1999
#1-2 years           2         5        22        46        53
#3-4 years           0         0         0         1         7
#5-6 years           0         0         0         0         0
#7-8 years           0         0         0         0         0
#9-10 years          0         0         0         0         0

(如果数据量充足,统计矩阵的对角线和上三角区域会被填充,下三角区域按构造逻辑默认全部为0。)


解答

逻辑合理性说明

你的实现逻辑完全符合需求:

  • 先通过坐标唯一识别位置、去重同一年同位置的多次事件,避免了无效计数,匹配你“不区分单位置事件总量、仅统计活跃年数”的规则
  • 逐步拓展累积时间窗口统计活跃年数、再按固定宽度分箱计数的方案,输出的矩阵可以直观反映观测周期拉长后,不同重复发生程度的位置数量变化趋势,完全可以量化你定义的遍历性特征。

代码优化建议

现有嵌套循环的方案在大数据量下重复计算开销很高,可以做以下优化提升运行效率:

  1. 避免循环内重复计算:不需要每次循环都做过滤、分组求和操作,可预计算每个位置的活跃年份集合,一次性统计各窗口的结果
  2. 简化中间步骤:不需要生成完整的坐标-年份交叉表,直接用count统计每个位置的活跃年数即可
  3. 参数化配置:把研究周期、分箱宽度等参数单独配置,后续调整不需要修改核心逻辑

优化后的参考实现:

library(dplyr)
library(tidyr)
library(purrr)

# 1. 预处理:生成每个位置的活跃年份集合
df_active <- df1 %>% 
  mutate(year = as.integer(year)) %>% 
  distinct(lng, lat, year) %>% 
  unite(coord, lng, lat, sep = ";")

# 2. 参数配置,可灵活调整
min_year <- 1990
max_year <- 1999
bin_width <- 2
n_window <- (max_year - min_year + 1) %/% bin_width
cutoff_years <- seq(min_year + bin_width -1, max_year, by = bin_width)

# 3. 一次性统计所有窗口的结果
result <- lapply(cutoff_years, function(cutoff) {
  df_active %>% 
    filter(year <= cutoff) %>% 
    group_by(coord) %>% 
    summarise(active_years = n(), .groups = "drop") %>% 
    mutate(
      freq_bin = cut(active_years, 
                     breaks = seq(0, max_year - min_year +1, by = bin_width),
                     labels = paste0(seq(1, max_year - min_year, by = bin_width), "-", 
                                     seq
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 12:33:00