在数据框中按组识别模式

时间:2016-12-12 17:55:13

标签: r date if-statement dplyr

我目前有一个数据集,显示每天按位置生病的人数。对于每个组(位置),在“病人”中输出1(生病)或0(不生病)。栏目,说明该地区是否有疾病。

我的目标是创建一个新列,用于识别长期疾病的时间段,并标记有助于此的任何行。

以下数据框显示了示例数据:

Current <- structure(list(Location = c("Madrid", "Madrid", "Madrid", "Madrid", 
"Madrid", "Madrid", "Madrid", "Madrid", "Madrid", "Madrid", "Madrid", 
"Madrid", "Madrid", "Madrid", "Madrid"), Date = structure(c(16122, 
16123, 16124, 16125, 16126, 16127, 16128, 16129, 16130, 16131, 
16132, 16133, 16134, 16135, 16136), class = "Date"), Sick = c(1, 
1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0)), .Names = c("Location", 
"Date", "Sick"), row.names = c(NA, -15L), class = c("tbl_df", 
"tbl", "data.frame"))

我想要应用于新列的规则如下:

*#如果在任何6天内有4天的疾病,记录病假的所有日子都应在新的计算变量中输入“长期”(&#39; Type&#39;)。如果不满足此条件,则应在新的计算变量中输入“短期”,该变量称为“类型”。

为此,我需要按组执行计算。位置是此分析中的组,因此我的目标是能够根据位置分类。我无法解决这个问题。

所需的输出如下所示:

Desired <- structure(list(Location = c("Madrid", "Madrid", "Madrid", "Madrid", 
    "Madrid", "Madrid", "Madrid", "Madrid", "Madrid", "Madrid", "Madrid", 
    "Madrid", "Madrid", "Madrid", "Madrid"), Date = structure(c(16122, 
    16123, 16124, 16125, 16126, 16127, 16128, 16129, 16130, 16131, 
    16132, 16133, 16134, 16135, 16136), class = "Date"), Sick = c(1, 
    1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0), Type = c(NA, NA, NA, 
    NA, NA, "Long Term", "Long Term", "Long Term", "Long Term", NA, 
    "Long Term", "Long Term", "Long Term", "Long Term", NA)), .Names = c("Location", 
    "Date", "Sick", "Type"), row.names = c(NA, -15L), class = c("tbl_df", 
    "tbl", "data.frame"))

非常感谢任何有关此问题的帮助,以及有关问题样式和布局的任何反馈都很有帮助。

目前,我遇到的问题是,只有满足ifelse标准的Window术语被标记为“长期”#39;。我需要的是所有形成窗口测试的观察结果,并且将疾病标记为1以标记长期&#39;:

2 个答案:

答案 0 :(得分:1)

一种方法是遵循@ Noobie的建议,找到&#34;长期&#34;句点,然后从那里扩展条目。在这里,我使用的是来自rollsum的{​​{1}},因为这是我熟悉的工作。重要的是,这假设每天都有一个条目(如果没有,请考虑使用来自zoo的{​​{1}} complete)并且它们是有序的(如果没有,请使用{{1 }})。

首先,找到长期开始的点:

full_seq

然后,为每个起点添加5天(使用tidyr以避免多次重新设置):

arrange

然后,为temp <- Current %>% mutate(rollCount = zoo::rollsum(Sick, 6 , fill = NA , align = "left") , startLong = rollCount >= 4) 添加一个列,并将其设置为unique,仅用于我们在toFill <- sapply(which(temp$startLong), function(x){ x + (0:5) }) %>% as.numeric() %>% unique() 中提取的内容:

Type

返回:

Long Term

如果要将其用于多个不同的位置,最好将其包装在函数中,然后使用toFilltemp$Type <- NA temp$Type[toFill] <- "Long Term" 添加列。

   Location       Date  Sick rollCount startLong      Type
      <chr>     <date> <dbl>     <dbl>     <lgl>     <chr>
1    Madrid 2014-02-21     1         3     FALSE      <NA>
2    Madrid 2014-02-22     1         3     FALSE      <NA>
3    Madrid 2014-02-23     0         3     FALSE      <NA>
4    Madrid 2014-02-24     0         4      TRUE Long Term
5    Madrid 2014-02-25     0         4      TRUE Long Term
6    Madrid 2014-02-26     1         5      TRUE Long Term
7    Madrid 2014-02-27     1         5      TRUE Long Term
8    Madrid 2014-02-28     1         5      TRUE Long Term
9    Madrid 2014-03-01     1         5      TRUE Long Term
10   Madrid 2014-03-02     0         4      TRUE Long Term
11   Madrid 2014-03-03     1        NA        NA Long Term
12   Madrid 2014-03-04     1        NA        NA Long Term
13   Madrid 2014-03-05     1        NA        NA Long Term
14   Madrid 2014-03-06     1        NA        NA Long Term
15   Madrid 2014-03-07     0        NA        NA Long Term

然后,将其应用于数据。请注意,应用此功能后,我使用group_bymutate的值设置为&#34;短期&#34;如果有疾病和空字符串(&#34;&#34;),如果没有。

myFunction <- function(x){
  temp <-
    data.frame(Sick = x) %>%
    mutate(rollCount = zoo::rollsum(Sick, 6
                                    , fill = NA
                                    , align = "left")
           , startLong = rollCount >= 4)

  toFill <-
    sapply(which(temp$startLong), function(x){
      x + (0:5)
    }) %>%
    as.numeric() %>%
    unique()

  temp$Type <- NA

  temp$Type[toFill] <- "Long Term"

  return(temp$Type)
}

返回:

ifelse

并且应该尊重不同的位置(同样,假设输入所有日期,行按日期排序)。

答案 1 :(得分:0)

解决方案:

在Pandas中使用滚动总和

df['flag'] = df.sickness.rolling(window = 6).sum()
df['long_term'] = (df['flag'] > 4)

或在R

library(RcppRoll)
library(dplyr)

mutate(df, flag = RcppRoll::roll_sum(x = sickness, 2),
       long_term = if_else(flag > 4, 'Bim!', 'Boom!'))