按区间查找列中的平均值

Finding Mean Values in a Column by Intervals

我正在跟踪治疗周前后的暴力事件,以查看治疗是否对其周围的事件计数有影响。 table 分为国家周,记录了 1989 年至 2019 年间大多数国家/地区的暴力事件。它与此类似,但总数约为。 120 个国家和 7 万行:

    Country  Year  Week  Event_Count  Treatment
    -------  ----  ----  -----------  ---------
    Angola   1995  33    3            NA
    Angola   1995  34    2            NA
    Angola   1995  35    3            NA
    Angola   1995  36    0            NA
    Angola   1995  37    4            1
    Angola   1995  38    1            NA
    Angola   1995  39    0            NA
    Angola   1995  40    2            NA
    Angola   1995  41    3            NA

我想找到在治疗周(在这种情况下,第 37 周由“治疗”列中的“1”表示)周围分成四个星期间隔的平均每周事件计数,直到十二周方向。换句话说,第 -1 周到 -4 周将是 2 个事件,因为这是第 33 周到第 36 周的平均每周事件计数。第 0 周(在本例中为第 37 周)将是 4 个。第 1 到第 4 周(第 38 到 41 周) ) 将是 1.5。第 -5 至 -8 周(第 29 至 32 周)、第 5 至第 8 周(第 42 至 45 周)、第 -9 至第 -12 周(第 25 至 28 周)和第 9 至 12 周(第 46 至 49 周)将是他们各自的垃圾箱。我正在使用回归不连续性设计,所以我想对刚刚错过接受治疗的国家做同样的事情,在治疗列中用“0”表示。处理列中的所有其他值均为“NA”。 我正在考虑这样编码:

    aggregate(df[row_interval, column_interval], list(df$Country), mean) 

但由于我将在同一个国家查看几个治疗周,并且治疗周有规律地变化(例如,安哥拉,1995 年第 37 周;阿尔及利亚,1998 年第 12 周等),这不会工作。理想情况下,我想将“0”和“1”的治疗输出与治疗周放在同一行中。例如:

    Country Year Week Event_Count Treatment -12to-9 -8to-5 -4to-1 0 1to4 5to8 9to12
    ------- ---- ---- ----------- --------- ------- ------ ------ - ---- ---- -----
    Algeria 2002  14     4           0         3      0.5    1    4  2    5    2

我试图将相似周的输出放在同一列中,无论接受“0”还是“1”治疗。例如,治疗后第 1 周至第 4 周的所有值都将归入“1to4”列。

提前感谢您的帮助!我对堆栈和 r 还很陌生,所以对于任何混淆我深表歉意。

我写了更长的数据,总共包含 25 周。

Country  Year  Week Event_Count Treatment
   <chr>   <dbl> <dbl>       <dbl>     <dbl>
 1 Angola   1995    25           3        NA
 2 Angola   1995    26           2        NA
 3 Angola   1995    27           4        NA
 4 Angola   1995    28           1        NA
 5 Angola   1995    29           0        NA
 6 Angola   1995    30           4        NA
 7 Angola   1995    31           1        NA
 8 Angola   1995    32           0        NA
 9 Angola   1995    33           3        NA
10 Angola   1995    34           2        NA
# ... with 15 more rows

与您的示例相同,第 37 周有 Treatment。 将函数 gola 定义为,

gola <- function(df) {
  idx <- which(!is.na(df$Treatment))
  res <- c()
  for (i in idx){
    trt <- df$Event_Count
    x.3 <- mean(trt[(i-12):(i-9)])
    x.2 <- mean(trt[(i-8):(i-5)])
    x.1 <- mean(trt[(i-4):(i-1)])
    x <- trt[i]
    x1 <- mean(trt[(i+1):(i+4)])
    x2 <- mean(trt[(i+5):(i+8)])
    x3 <- mean(trt[(i+9):(i+12)])
    res <- rbind(res,c(x.3, x.2, x.1, x, x1, x2, x3))
    
  }
  colnames(res) <- c("_12to_9", "_8to_5", "_4to_1", "0", "1to4", "5to8", "9to12")
  res <- cbind(df[idx,], res)
  return(res) 
}

然后,gola(df)将return

  Country Year Week Event_Count Treatment _12to_9 _8to_5 _4to_1 0 1to4 5to8 9to12
1  Angola 1995   37           4         1     2.5   1.25      2 4  1.5    2  1.75

这就是我得到的。我没有你的实际数据。因此,我创建了自己的示例数据,它与您的相似。根据您的实际数据,我的想法 may/may 不适合您。但我认为这个想法对解决你的案子有一定的意义。我认为关键是如何生成子组索引。您有一个基本行,其中您在治疗中有 0、1 或 NA。 (在我的示例中,我只使用了 1。您需要考虑在 Treatment 中没有任何 1 或 0 的情况。)基本上,我想确定可以用作创建子组的标志的行号。当您想要识别此类行时,您需要考虑行号何时比基行数 smaller/larger 。您在第一个 case_when() 中看到了这一点。第二个 case_when() 处理生成组号。在此之后,这项工作似乎很简单。希望对你有所帮助。

group_by(mydf, Country) %>%
  mutate(group = 1:n(),
         group = case_when(row_number() %in% (which(Treatment == 1) + 
                                       (4 * 1:floor(length(group[which(Treatment == 1):n()]) / 4)) + 1) ~
                         TRUE,
                  row_number() %in% (which(Treatment == 1) - 
                                            (4 * 1:floor(length(group[1:which(Treatment == 1)]) / 4)) - 1) ~
                         TRUE,
                  row_number() == which(Treatment == 1) ~ TRUE,
                         TRUE ~ FALSE),
         group = case_when(row_number() < which(Treatment == 1) ~
                             cumsum(c(T, diff(group) == -1)),
                           row_number() > which(Treatment == 1) ~
                             cumsum(c(F, diff(group) == 1)) + as.integer(100),
                           TRUE ~ as.integer(100))) %>% 
 group_by(group, .add = TRUE) %>% 
 summarize(year = first(Year),
           week = paste(first(Week), last(Week), sep = "-"),
           average = mean(Event_Count, rm.na = TRUE)) %>% 
 select(-group)

#  Country    year week  average
#   <chr>     <dbl> <chr>   <dbl>
# 1 Argentina  1995 24-24    4   
# 2 Argentina  1995 25-28    5   
# 3 Argentina  1995 29-32    7.25
# 4 Argentina  1995 33-36    7.75
# 5 Argentina  1995 37-37    8   
# 6 Argentina  1995 38-41    3.5 
# 7 Argentina  1995 42-45    7.253
# 8 Argentina  1995 46-49    5.25
# 9 Argentina  1995 50-50    9   
#10 Brazil     1995 24-24    4   
#11 Brazil     1995 25-28    5   
#12 Brazil     1995 29-32    6   
#13 Brazil     1995 33-36    7.5 
#14 Brazil     1995 37-37    7   
#15 Brazil     1995 38-41    6.5 
#16 Brazil     1995 42-45    4   
#17 Brazil     1995 46-49    6.5 
#18 Brazil     1995 50-50   10  

数据

set.seed(111)
mydf <- data.frame(Country = rep(c("Argentina", "Brazil"), each = 27),
                   Year = rep(1995, times = 54),
                   Week = rep(c(24:50), times = 2),
                   Event_Count = sample.int(n = 10, size = 54, replace = TRUE),
                   Treatment = rep(c(rep(NA, times = 13), 1, rep(NA, times = 13)), times = 2))