首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用过去迭代对移动窗口进行矢量化

用过去迭代对移动窗口进行矢量化
EN

Stack Overflow用户
提问于 2019-05-07 19:51:01
回答 3查看 94关注 0票数 2

给出一个非常大的数据集(>100万次观测),并试图将我的逻辑向量化,但没有找到R化的方法来解决它。

问题是,每当我在变量中有一个“坏”的观察时,我需要检查前面的5个观察结果是否有“好的”指标。只要前面有5个“好”的观察,“坏”的观察就会被保留下来。如果在5个观测移动窗口中存在“坏”观测,那么该观测结果最终将被从分析中删除。

到目前为止,我已经尝试使用带有ifelse()逻辑的for循环。逻辑检验出来了,但是R的处理需要几个小时才能完成。我已经研究过用于滚动窗口的zoo包,但没有应用聚合函数,比如mean()sum()。我还研究过apply()lapply()等,但一直无法使它们工作。

这是我的代码,所以是for循环。让df$Observation作为好与坏的最初标记,让df$Result来决定我们是保持还是放弃观察。

编辑

代码语言:javascript
复制
set.seed(1)
df <- data.frame(Observation = sample(c("Good", "Bad"), 1000, T, c(0.9,0.1)))

for(i in 1:nrow(df)){
  ifelse(
    df$Observation[i] == "Good",
    df$Result[i] <- "Keep",
    ifelse(
      df$Observation[i] == "Bad" &
        df$Observation[i-1] == "Good" &
        df$Observation[i-2] == "Good" &
        df$Observation[i-3] == "Good" &
        df$Observation[i-4] == "Good",
      df$Result[i] <- "Keep",
      df$Result[i] <- "Drop"
    )
  )
}

期望结果示例:

代码语言:javascript
复制
df[385:393,]

    Observation Result
385        Good   Keep
386        Good   Keep
387        Good   Keep
388        Good   Keep
389        Good   Keep
390         Bad   Keep
391        Good   Keep
392        Good   Keep
393         Bad   Drop

代码如预期的工作,但我需要一个更有效的方式来执行它在R。谢谢你的帮助!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-05-07 20:06:47

你可以这样做:

首先,我设置了种子,创建了一些样本数据,并打开了必要的包。

代码语言:javascript
复制
set.seed(1)
df <- data.frame(Observation = sample(c("Good", "Bad"), 1000, T, c(0.9,0.1)))
library(zoo)
library(dplyr)

一开始我落后了一排。从这里开始,我计算了该滞后行和前四行的rollmax。然后,我将这个rollmax1进行比较。如果计算结果为TRUE,当前行等于"Bad",则Result"Drop",否则为"KEEP"

代码语言:javascript
复制
df2 <- df %>% 
  mutate(Result = if_else(rollmax(lag(Observation) == "Bad", 5, fill = 0, align = "right") == 1 & Observation == "Bad", "Drop", "Keep")) 

这样,它将与预期的输出相匹配:

代码语言:javascript
复制
 df2[385:393,]
    Observation Result
385        Good   Keep
386        Good   Keep
387        Good   Keep
388        Good   Keep
389        Good   Keep
390         Bad   Keep
391        Good   Keep
392        Good   Keep
393         Bad   Drop
票数 1
EN

Stack Overflow用户

发布于 2019-05-09 03:14:47

为此,我喜欢zoo。这一切似乎都匹配,除了第一次的坏(只有3个国家之前)。您可以使用fill = 4调整逻辑以保持该逻辑不变。

代码语言:javascript
复制
library(tidyverse)
library(zoo)

df_decision <-
  df %>% 
  mutate(
    good_ind = as.integer(Observation == "Good"),
    good_count = rollsum(good_ind, 5, align = "right", fill = good_ind),
    result =ifelse(good_ind == 1 | good_count >= 4, "keep", "drop")
  )
票数 2
EN

Stack Overflow用户

发布于 2019-05-08 20:51:03

如果用一些dplyr函数替换循环,事情就会加快。只是要小心前5排的处理。dplyr版本将在前5行中删除任何“不好”的观察结果,而循环将保留它们。如果需要,可以向case_when添加更多的逻辑。

代码语言:javascript
复制
library(tictoc)
library(dplyr)

set.seed(1)
df <- data.frame(Observation = sample(c("Good", "Bad"), 10000, TRUE, c(0.9,0.1)))
df2 <- df

tic("loop")
for(i in 1:nrow(df)){
  ifelse(
    df$Observation[i] == "Good",
    df$Result[i] <- "Keep",
    ifelse(
      df$Observation[i] == "Bad" &
        df$Observation[i-1] == "Good" &
        df$Observation[i-2] == "Good" &
        df$Observation[i-3] == "Good" &
        df$Observation[i-4] == "Good",
      df$Result[i] <- "Keep",
      df$Result[i] <- "Drop"
    )
  )
}
toc() # 3.9s

tic("dplyr")
df2 <- df2 %>% 
  dplyr::mutate(
    L1 = dplyr::lag(Observation, 1),
    L2 = dplyr::lag(Observation, 2),
    L3 = dplyr::lag(Observation, 3),
    L4 = dplyr::lag(Observation, 4),
    L5 = dplyr::lag(Observation, 5),
    Result = dplyr::case_when(
      Observation == "Good" ~ "Keep",
      L1 == "Good" & 
        L2 == "Good" & 
        L3 == "Good" & 
        L4 == "Good" & 
        L5 == "Good" ~ "Keep",
      TRUE ~ "Drop"
    )
  ) %>% 
  dplyr::select(Observation, Result)
toc() # 0.08s
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56029580

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档