【问题标题】:How to subset a data frame by the last day of each month如何按每个月的最后一天对数据框进行子集化
【发布时间】:2012-09-19 09:56:17
【问题描述】:

我有一个 df :

     dates  V1  V2  V3  V4  V5  V6  V7  V8  V9  V10
1999-05-31  66  65  64  63  62  61  60  59  58  57
1999-06-01  67  66  65  64  63  62  61  60  59  58
1999-06-02  68  67  66  65  64  63  62  61  60  59
1999-06-03  69  68  67  66  65  64  63  62  61  60
1999-06-04  70  69  68  67  66  65  64  63  62  61
1999-06-17  79  78  77  76  75  74  73  72  71  70
1999-06-18  80  79  78  77  76  75  74  73  72  71
1999-06-21  81  80  79  78  77  76  75  74  73  72
1999-06-22  82  81  80  79  78  77  76  75  74  73
1999-06-23  83  82  81  80  79  78  77  76  75  74
1999-06-24  84  83  82  81  80  79  78  77  76  75
1999-06-25  85  84  83  82  81  80  79  78  77  76
1999-06-28  86  85  84  83  82  81  80  79  78  77
1999-06-29  87  86  85  84  83  82  81  80  79  78
1999-06-30  88  87  86  85  84  83  82  81  80  79

我想在每个月的最后一天对上述 df 进行子集化。也就是说,只有日期 1999-05-31 和 1999-06-30 会出现。实际数据框要大得多,最后日期可能是每个月的 28 日、29 日等。 所以我希望输出是这样的:

dates   V1  V2  V3  V4  V5  V6  V7  V8  V9  V10
1999-05-31  66  65  64  63  62  61  60  59  58  57 
1999-06-30  88  87  86  85  84  83  82  81  80  79
1999-10-29  175 174 173 172 171 170 169 168 167 166

我试图在 zoo 或其他包中找到一些功能,但找不到...非常感谢所有建议!

【问题讨论】:

    标签: r xts zoo


    【解决方案1】:

    假设日期格式正确,源数据框为x

    > library(xts)
    > x[endpoints(x$dates, on = "months"), ]
            dates V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
    1  1999-05-31 66 65 64 63 62 61 60 59 58  57
    15 1999-06-30 88 87 86 85 84 83 82 81 80  79
    

    【讨论】:

    • 谢谢!那么我怎样才能找到每个月的第一次观察呢?我可以简单地做 x[endpoints(x$dates, on = "months")+1, ] 还是有一些特定的功能?最好的问候!
    【解决方案2】:

    这会选择当月的最后几天:

    df[as.numeric(substr(as.Date(df$dates) + 1, 9, 10))
       < as.numeric(substr(df$dates, 9, 10)), ]
    
    #        dates V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
    #1  1999-05-31 66 65 64 63 62 61 60 59 58  57
    #15 1999-06-30 88 87 86 85 84 83 82 81 80  79
    

    请注意,此解决方案取决于每天的绝对月数(与您的数据无关)。

    如果您想在实际数据中选择每个月的最后一天,请使用以下命令:

    df[c(diff(as.numeric(substr(df$dates, 9, 10))) < 0, TRUE), ]
    

    【讨论】:

    • 再次感谢斯文!你有很棒的 R 技能!
    • 好的!谢谢!:) 但是为什么包含TRUE?如果我排除它,我似乎得到了相同的答案......
    • 命令diff(as.numeric(substr(df$dates, 9, 10))) &lt; 0 返回一个长度为nrow(df)-1 的逻辑向量,因此我将这个向量与一个额外的TRUE 结合起来,以使用它来选择df 的行子集。向量的长度和逻辑索引向量的长度应该相同。如果逻辑索引短了一个元素,则逻辑向量的第一个值也将用作其最后一个值。
    • 如果我想找到每个月的第一天而不是每个月的最后一天,我是否正确地认为我可以更改 df[c(diff(as.numeric(substr(df$dates) , 9, 10))) 0, TRUE), ] ? :)
    • @user1665355 不,只是改变TRUE的位置:df[c(TRUE, diff(as.numeric(substr(df$dates, 9, 10))) &lt; 0), ]
    【解决方案3】:

    这是一个使用dplyr的选项:

    library(dplyr)
    
    df %>% 
      mutate(dates = as.Date(dates)) %>% 
      mutate(yr_mnth = format(dates, '%Y-%m')) %>% 
      group_by(yr_mnth) %>% 
      filter(dates == max(dates))
    
    # or if you wanted the first observation of each month:
    df %>% 
      mutate(dates = as.Date(dates)) %>% 
      mutate(yr_mnth = format(dates, '%Y-%m')) %>% 
      group_by(yr_mnth) %>% 
      filter(dates == min(dates))
    

    【讨论】:

      猜你喜欢
      • 2014-11-13
      • 1970-01-01
      • 1970-01-01
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      相关资源
      最近更新 更多