【问题标题】:Identifying Patterns by Group in a Data Frame在数据框中按组识别模式
【发布时间】:2017-04-27 15:52:44
【问题描述】:

我目前有一个数据集,该数据集显示了每天按地点划分的患病人数。对于每个组(位置),在“生病”列中输出 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 天的病假,则所有记录病假的天数都应在新的计算变量(“类型”)中输入“长期”。如果不满足此条件,则应在称为“类型”的新计算变量中输入“短期”。

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

所需的输出如下所示:

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 术语被标记为“Long Term”。我需要的是所有形成窗口测试并且疾病为 1 的观察结果都被标记为“长期”:

【问题讨论】:

    标签: r date if-statement dplyr


    【解决方案1】:

    解决方案:

    在 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!'))
    

    【讨论】:

    • 标签错误。您提供的是 pandas 解决方案。
    • 哈哈确实!无论如何,这个想法保持不变。 OP 应该在这里使用滚动总和。
    • 也许你应该改变你的答案。
    • 嗨,该解决方案的工作原理是它只标记满足 long_term 条件的一天。我希望该窗口中的所有疾病观察都贴上“如果 if 语句为真,则长期存在”的标签。谢谢
    • @Noobie 知道如何根据该标准进行标记吗?谢谢
    【解决方案2】:

    一种方法是按照@Noobie 的建议找到“长期”期的开始,然后从那里扩展条目。在这里,我使用来自zoorollsum,只是因为这是我熟悉的工作。重要的是,这假设每天都有一个条目(如果没有,请考虑使用complete 和来自tidyrfull_seq)并且它们是有序的(如果没有,请使用arrange)。

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

    temp <-
      Current %>%
      mutate(rollCount = zoo::rollsum(Sick, 6
                                      , fill = NA
                                      , align = "left")
             , startLong = rollCount >= 4)
    

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

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

    然后,为Type 添加一列,并将其设置为Long Term,仅用于我们拉入toFill 的那些:

    temp$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 添加列。

    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)
    }
    

    然后,将其应用于数据。请注意,应用该功能后,我使用ifelseType 的值设置为“短期”,如果有病,则为空字符串(“”)。

    Current %>%
      group_by(Location) %>%
      mutate(Type = myFunction(Sick)
             , Type = ifelse(Sick == 1
                             , ifelse(!is.na(Type)
                                      , Type, "Short Term")
                             , ""))
    

    返回:

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

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

    【讨论】:

    • 嗨@Mark Peterson,感谢您的回复。这看起来不错,但是否可以在 'Sick' = 1 的观察结果上使用类型标签?
    • 我不确定您所说的“只有”标签是什么意思。所以在编辑中,我在没有生病时将其设置为空(“”),在生病时将其设置为“短期”。您可以将其放在函数中,但似乎足够合理,将其拉出此处。
    • 例如,“Returns”表的第 10 行的 Type 变量中包含“Long Term”,尽管当天没有生病。当 'Sick' =1 时,需要将什么调整为只有 'Type' 的标签?
    • 顺便说一句,我得到了错误:错误:k
    • 我现在明白你的意思,并再次编辑(需要更改 ifelse 一点)。我的猜测是您输入的日期为 6 个或更少的位置(窗口的大小称为 k,因此这表明您的点数少于窗口的宽度)
    猜你喜欢
    • 1970-01-01
    • 2021-03-16
    • 2019-03-21
    • 2017-08-19
    • 2017-04-29
    • 2012-12-29
    • 1970-01-01
    • 2017-02-14
    • 1970-01-01
    相关资源
    最近更新 更多