【问题标题】:Remove rows of NA values, if they occur for a specific time range in loop to slow?删除 NA 值的行,如果它们发生在循环中的特定时间范围内变慢?
【发布时间】:2019-11-07 08:35:24
【问题描述】:

我是 R 新手,所以如果我问一个明显的问题,我很抱歉。我搜索了一周,但没有找到解决方案。

我有一个包含许多列和行的数据框。 现在我想删除所有行,如果:

A 列的时间范围为例如仅 8 小时 NA 值 然后删除该范围内的所有行。

背景:最初我想删除周末发生的行,因为这不是工作日/小时。但是我在一周中也没有“随机”发生的工作日/小时。所以我只想要设备实际工作的数据。而且我的表并没有因为这个不是真正的缺失值的“缺失值”而搞砸。

我找到的唯一一段代码如下:

df[-which(rowMeans(is.na(df)) > 0,3), ]

我认为有可能根据我的条件修改此代码,但我不知道。 目前它只查看每一行并决定是否有超过 30% 的 NA。但这还不够,因为我有几个星期的数据,在此之前我无法说出 NA 出现的频率和时间范围。

这里是一个例子:

df <- data.frame(DateTime = c('2019-05-31 08:23:00', '2019-05-31 09:46:00', '2019-05-31 10:00:00', '2019-05-31 11:07:00', '2019-05-31 11:10:00','2019-05-31 11:56:00', '2019-05-31 12:06:00', '2019-05-31 12:56:00', '2019-05-31 14:16:00', '2019-05-31 15:45:00', '2019-05-31 16:03:00', '2019-05-31 17:05:00', '2019-05-31 18:00:00', '2019-05-31 19:30:00', '2019-05-31 20:01:00'),
             A=c(NA, 1, 2, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA ),
             B = c(NA, 2.4, 3, 5, NA, NA, 2.5, NA, NA, 2.6, NA, NA, NA, 1, 2)) 


      DateTime  A   B
1  2019-05-31 08:23:00 NA  NA
2  2019-05-31 09:46:00  1 2.4
3  2019-05-31 10:00:00  2 3.0
4  2019-05-31 11:07:00 NA 5.0
5  2019-05-31 11:10:00 NA  NA
6  2019-05-31 11:56:00 NA  NA
7  2019-05-31 12:06:00 NA 2.5
8  2019-05-31 12:56:00 NA  NA
9  2019-05-31 14:16:00 NA  NA
10 2019-05-31 15:45:00 NA 2.6
11 2019-05-31 16:03:00 NA  NA
12 2019-05-31 17:05:00 NA  NA
13 2019-05-31 18:00:00 NA  NA
14 2019-05-31 19:30:00 NA 1.0
15 2019-05-31 20:01:00 NA 2.0

另外还有一个说法是,我没有与时间范围相对应的固定数量的行。 NA 值可以在定义的 8 小时时间范围内出现 8,76 或 10 次。

这就是我想要的样子:

DateTime             A   B
1  2019-05-31 08:23:00 NA  NA
2  2019-05-31 09:46:00  1 2.4
3  2019-05-31 10:00:00  2  NA
4  2019-05-31 20:01:00  1 2.0

我希望我正确地描述了我的问题,并且有人能够帮助我。

非常感谢!

更新:我找到了一个循环解决方案,但它非常缓慢。有人可以提出更快的建议吗?对于 400k 行,循环需要 1 小时...因此,行数每天都在增加,这不是使用循环运行的解决方案。

代码如下: A

startIndex = -1

for(i in 1:nrow(AggregatedTable))                    
{ 
  if (is.na(A[i]))                      
  {
    if (startIndex == -1)
    {
      startIndex = i;
    }
  }
  else 
  {         
    if (startIndex != -1)
    {
      lastIndex = i - 1
      if((difftime(D[lastIndex], D[startIndex]) >= 8)) 
      {    
        AggregatedTable <- AggregatedTable[-(startIndex:lastIndex), , drop = FALSE]
      } 
      startIndex = -1
    }
   }
}

【问题讨论】:

    标签: r conditional-statements na posixct


    【解决方案1】:

    我们根据NA 的出现创建一个分组变量,rleidfilter 基于行数

    library(dplyr)
    library(data.table)
    df %>% 
       group_by(grp = rleid(is.na(A))) %>%
       filter(!(n() >= 8 & all(is.na(A)))) %>%
       ungroup %>%
       select(-grp)
    # A tibble: 5 x 3
    #  DateTime                A     B
    #  <fct>               <dbl> <dbl>
    #1 2019-05-31 08:23:00    NA  NA  
    #2 2019-05-31 09:46:00     1   2.4
    #3 2019-05-31 10:00:00     2  NA  
    #4 2019-05-31 11:07:00     3  NA  
    #5 2019-05-31 20:01:00     1   2  
    

    【讨论】:

    • 得到答案的速度让我印象深刻。谢谢@akrun。但是通过这种方式,我们不考虑时间,只考虑行数。在我的情况下,8 小时与行数不对应,因为我的频率不规则。那么,如果我在某些情况下在这 8 小时内有 18 行,而在另一种情况下在这 8 小时内有 50 行,情况会怎样?
    • @Irina3891 我以为你的“日期时间”是arranged。如果没有安排,那么你可能需要先arrange df %&gt;% arrange(ymd_hms(DateTime)) %&gt;% from lubridate
    • @Irina3891 您是否有时间差超过 1 小时的数据(即使在安排后),然后您想跳过这些数据?你能用那种例子更新你的帖子吗
    • 数据是有序的。但随着时间的推移,我没有相同的频率。数据是随机保存的。所以每小时没有值,但有时每小时有 10 个值/行,有时只有 3 个值/行。所以不可能说 1 小时是 1 个 NA 值。
    • 我更新了示例数据。希望现在更清楚一点?
    猜你喜欢
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 2020-12-30
    • 2019-09-19
    • 2022-10-14
    • 1970-01-01
    • 1970-01-01
    • 2016-03-27
    相关资源
    最近更新 更多