r - For 循环 - 从日列中选择时间窗口

标签 r for-loop time dataframe window

我需要调整一个代码,它与我的数据框完美配合(但使用另一个设置),以便从列 Day 中选择一个 2 天的时间窗口。特别是我对第 0 天之前的 1 天(即 i - 1 和 i,其中 i 是感兴趣的日期)及其包含在列 Count 中的 (i - 1) 值感兴趣必须添加到第 0 天(i ) col 计数。

这是我的数据框的示例:

df <- read.table(text = "
        Station   Day           Count
    1    33012  12448               4
    2    35004  12448               4
    3    35008  12448               4
    4    37006  12448               4
    5    21009   4835               3
    6    24005   4835               3
    7    27001   4835               3
    8    25005  12447               3
    9    29001  12447               3
    10   29002  12447               3
    11   29002  12446               3
    12   30001  12446               3
    13   31002  12446               3
    14   47007   4834               2
    15   49002   4834               2
    16   47004  12445               1
    17   51001  12449               1
    18   51003   4832               1
    19   52004   4836               1", header = TRUE)

我的输出应该是:
           Station    Day           Count
        1    33012  12448               7
        2    35004  12448               7
        3    35008  12448               7
        4    37006  12448               7
        5    21009   4835               5
        6    24005   4835               5
        7    27001   4835               5
        8    29002  12446               4
        9    30001  12446               4
        10   31002  12446               4
        11   51001  12449               1
        12   51003   4832               1
        13   52004   4836               1
        14   25005  12447               0
        15   29001  12447               0
        16   29002  12447               0
        17   47007   4834               0
        18   49002   4834               0
        19   47004  12445               0

我正在尝试此代码,但它不适用于我的真实数据框:
for (i in unique(df$Day)) {
    temp <- df$Count[df$Day == i]  
    if(length(temp > 0)) {  
    condition1 <- df$Day == i - 1   
    if (any(condition1)) {
       df$Count[df$Day == i] <- mean(df$Count[condition1]) + df$Count[df$Day == i]
       df$Count[condition1] <- 0
            }
         }
}

代码看起来是正确的,它有道理,但我的输出不是。

任何人都可以帮助我吗?

@aichao 代码效果很好。

如果我想考虑前 30 天(即第 30 天、第 29 天、第 28 天、....、第 1 天、第 0 天),是否有任何快速的方法可以做到这一点,而不是创建 30 if 语句(条件)?

再次感谢@aichao 的帮助。

最佳答案

以下对您提供的示例数据执行您想要的操作

for (i in unique(df$Day)) {
  temp <- df$Count[df$Day == i]
  if (any(temp > 0)) {
    condition1 <- df$Day == i - 1
    condition1[which(df$Day == i - 1) < max(which(df$Day == i))] <- FALSE
    if (any(condition1)) {
      df$Count[df$Day == i] <- mean(df$Count[condition1]) + df$Count[df$Day == i]
      df$Count[condition1] <- 0
    }
  }
}
print(df[order(df$Count, decreasing = TRUE),])
##   Station   Day Count
##1    33012 12448     7
##2    35004 12448     7
##3    35008 12448     7
##4    37006 12448     7
##5    21009  4835     5
##6    24005  4835     5
##7    27001  4835     5
##11   29002 12446     4
##12   30001 12446     4
##13   31002 12446     4
##17   51001 12449     1
##18   51003  4832     1
##19   52004  4836     1
##8    25005 12447     0
##9    29001 12447     0
##10   29002 12447     0
##14   47007  4834     0
##15   49002  4834     0
##16   47004 12445     0

从您的评论中发现的一个关键要求在您的实现中遗漏了,即在确定前一天及其计数时,仅考虑数据框下方(按行)的天数。也就是说,您正在处理数据框行,就好像它们是按时间排序的一样,而不考虑 Day 中的值。列作为时间顺序。因此,对于 df$Day = 12449没有前一天需要考虑,因为所有行都带有 df$Day = 12448在它之前。结果,Countdf$Day = 12449保持在 1 ,更重要的是,Counts对于所有具有 df$Day = 12448 的行处理后不归零df$Day = 12449 .

为了实现这一点,我们需要进一步过滤 condition1所以我们设置为 FALSE df$Day == i - 1 的所有行(前一天)在 df$Day == i 的最高行之前(感兴趣的日子)使用该行
condition1[which(df$Day == i - 1) < max(which(df$Day == i))] <- FALSE

请注意,此解决方案假定 Day 的值相同数据框中的列与示例数据中的行块一样集中在一起。否则,您的 for循环 unique(df$Day)需要完全重新考虑并替换为行上的循环,以便跟踪数据框中感兴趣的日期的当前行。

此外,您的代码中有一个小错误在行中
if(length(temp > 0)) {

目的是检查是否有任何行 Count大于 0对于感兴趣的日子。然而,R 中的条件运算符被向量化,使得 temp > 0返回与输入长度相同的 bool 值向量 temp .因此,length(temp > 0)除非 temp,否则将始终返回正数本身的长度 0 (即,空)。为了达到您的目的,该行更改为
if(any(temp > 0)) {

更新:关于前几天的新要求

解决新需求的最简单方法是将代码体放在 if (any(temp > 0)) {...} 中。阻塞到一个函数中,调用它 accumulate.mean.count ,并使用 sapply 将此函数应用于前几天的集合.修改内容为:
accumulate.mean.count <- function(this.day, lag) {
  condition1 <- df$Day == this.day - lag
  condition1[which(df$Day == this.day - lag) < max(which(df$Day == this.day))] <- FALSE
  if (any(condition1)) {
    df$Count[df$Day == this.day] <<- mean(df$Count[condition1]) + df$Count[df$Day == this.day]
    df$Count[condition1] <<- 0
  }
}

lags <- seq_len(30)

for (i in unique(df$Day)) {
  temp <- df$Count[df$Day == i]
  if (any(temp > 0)) {
    sapply(lags, accumulate.mean.count, this.day=i)
  }
}

print(df[order(df$Count, decreasing = TRUE),])

笔记:
  • lag是当天(即滞后)之前的天数。一个 lag = 1表示前一天,以及 lag = 2表示前两天,以此类推 lags是这些的集合。在这里,lags <- seq_len(30)是来自 1 的序列至 30在哪个accumulate.mean.count已应用,这就是您想要的。见 this有关 *apply 的出色概述R 函数族。请注意 lags不一定是一个序列,而只是一个整数的集合,例如 c(1, 5, 10)前一天、前 5 天和前 10 天。如果您想在 future 几天滚动,它甚至不必为正,但不应为零。
  • 因为lexical scoping rule of R , 设置 df$Count ,这是一个超出 accumulate.mean.count 范围的变量, 在函数内 accumulate.mean.count需要 <<-而不是 <- .见 this解释并注意使用 <<- 的危险那里提到。

  • 我没有足够的数据来测试 lags <- seq_len(30) , 但对于 seq_len(1) ,我恢复了原来的结果,对于seq_len(2) , 我有
    ##   Station   Day Count
    ##1    33012 12448    10
    ##2    35004 12448    10
    ##3    35008 12448    10
    ##4    37006 12448    10
    ##5    21009  4835     5
    ##6    24005  4835     5
    ##7    27001  4835     5
    ##16   47004 12445     1
    ##17   51001 12449     1
    ##18   51003  4832     1
    ##19   52004  4836     1
    ##8    25005 12447     0
    ##9    29001 12447     0
    ##10   29002 12447     0
    ##11   29002 12446     0
    ##12   30001 12446     0
    ##13   31002 12446     0
    ##14   47007  4834     0
    ##15   49002  4834     0
    

    我相信这是你想要的。

    关于r - For 循环 - 从日列中选择时间窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38394092/

    相关文章:

    r - 如何在 R 中将时间数据拆分为时间间隔?

    r - 在R中创建空的csv文件

    c - 在 for 循环中使用模数

    python - 为什么低于 0.25 的 time() 会跳过 Python 中的动画?

    java - 在单元测试中操纵当前时间?

    r - 在 R 中将矩阵的对角线设置为零

    r - 为文件夹中的多个文件计算两列之间的 r 平方,并使用 R 将结果写入单个文件

    php - 从php中的一系列数组键中跳过键索引

    PHP - 时差(HH :MM format)

    r - 使用 R 的 lm(),公式对象应该作为字符传递吗?