【问题标题】:How to select the last day of the month in R如何在R中选择一个月的最后一天
【发布时间】:2017-05-03 06:25:16
【问题描述】:

如何选择当月最后一天对应的数据? 例如,我有一个数据集,其中包含从 2000 年到 2016 年的V1 的每日数据。我只需要选择每个月的最后一天,即所有年份的31/01/200128/02/2001 等。日期格式为DD/MM/YYYY

 V1         V2
4.59 29/12/2000
4.59 01/01/2001
4.58 02/01/2001
4.52 03/01/2001
4.54 04/01/2001
4.58 05/01/2001
......
4.09 26/01/2001
4.50 27/01/2001
4.18 28/01/2001
4.11 29/01/2001
3.54 30/01/2001
4.98 31/01/2001  <- Select this row!

【问题讨论】:

  • 这真的是非常基本的分组子集并对其进行操作(使用max()。Joel Wilson 的答案将其解决为单线(我在评论中提到的两个小警告)。

标签: r date select


【解决方案1】:
library(data.table)
library(lubridate)

# for each unique combo of year-mon get the last entry
setDT(df)[order(V2), .(V1[which.max(V2)], V2[which.max(V2)]), by = .(year(V2), month(V2))] 
#   year month   V1         V2
#1: 2000    12 4.59 2000-12-29
#2: 2001     1 4.98 2001-01-31

【讨论】:

  • 这个答案是正确的,例如与 akrun 答案中的示例数据一起工作如果您将第二列变成日期类型,例如通过df[,2] &lt;- anytime::anydate(df[,2])。你也不需要包lubridate,因为data.table已经有year()month()等pp
【解决方案2】:

这也可以使用基础 R 来完成。

df[df$V2 %in% unique(as.Date(format(df$V2 + 28, "%Y-%m-01")) - 1),]
    V1         V2
12 4.98 2001-01-31

这使用了我从 Dirk Dirk Eddelbuettel 的 SO 答案之一中获得的技巧。想法是将日期设置为下个月的第一天,然后从中减去 1。

数据

df <- structure(list(V1 = c(4.59, 4.59, 4.58, 4.52, 4.54, 4.58, 4.09, 
4.5, 4.18, 4.11, 3.54, 4.98), V2 = structure(c(11320, 11323, 
11324, 11325, 11326, 11327, 11348, 11349, 11350, 11351, 11352, 
11353), class = "Date")), .Names = c("V1", "V2"), row.names = c(NA, 
-12L), class = "data.frame")

概念证明

# construct a vector of dates for 10 years, 2001 through 2010
myDates <- seq(as.Date("2001-01-01"), as.Date("2010-12-31"), by="day")

# pull off the final days of the month
finalDays <-
       myDates[myDates %in% unique(as.Date(format(myDates + 28, "%Y-%m-01")) - 1)]

# Take a look at first 5 and last 5
c(head(finalDays, 5), tail(finalDays, 5))
 [1] "2001-01-31" "2001-02-28" "2001-03-31" "2001-04-30" "2001-05-31"
 [6] "2010-08-31" "2010-09-30" "2010-10-31" "2010-11-30" "2010-12-31"

# get length, 12 * 10 = 120
length(finalDays)
[1] 120

# make sure there are no repeated values
length(unique(finalDays))
[1] 120

【讨论】:

  • 在该位置有+28 会导致将数字添加到因子时出错。删除它我只会得到无效的修剪参数。
  • 它没有返回正确的日期数……有不少人被跳过了!
  • 它适用于您提供的示例。您的评论太模糊,无法进一步添加任何内容。请花时间阅读how to provide a great R example 上的这篇文章以及如何提供minimal, complete, and verifiable example 并相应地修改您的问题。
  • 我明白..但我有 16 年期间的每日数据...我真的不知道我该如何帮助您...
  • 这确实适用于您的数据......但在我的数据中却没有。我应该有184个月。但相反,我得到 133。
【解决方案3】:
subset(df, as.POSIXlt(V2 + 1)$mday == 1)

## you don't have 31-Dec in your data
#     V1         V2
# 1 4.98 31/01/2001

【讨论】:

  • 我明白了:Warning message: In Ops.factor(V2, 1) : ‘+’ not meaningful for factors
  • 查看其他答案,了解如何将变量转换为日期
  • 好的!那么只是转换是错误的原因..确定!
  • 但是它没有返回正确的日期数!例如,不返回 03/2001 的最后一天。
  • @HA,请提供最少的自包含可重现示例。这是一个这样的示例,表明它确实有效:subset(data.frame(V2 = as.Date("2001-03-31")), as.POSIXlt(V2 + 1)$mday == 1)
【解决方案4】:

我们可以使用dplyr

library(dplyr)
library(lubridate)
library(zoo)

如果我们只需要一个月的最后一天而不是在数据集中找到的最后一天

 df %>% 
      filter(dmy(V2) == as.Date(as.yearmon(dmy(V2)), frac=1))
 #    V1         V2
 #1 4.98 31/01/2001

但是,如果我们需要过滤每个月在数据集中找到的最后一天

df %>%
    mutate(V3 = dmy(V2))%>%
    group_by(month = month(V3), year = year(V3)) %>%
    slice(which.max(day(V3))) %>%
    ungroup() %>%
    select(-month, -year, -V3)
#     V1         V2
#   <dbl>      <chr>
#1  4.98 31/01/2001
#2  4.59 29/12/2000

如果只按“月”分组,只需去掉group_by中的year = year(V3))就可以了

df %>%
    mutate(V3 = dmy(V2))%>%
    group_by(month = month(V3)) %>%
    slice(which.max(day(V3))) %>%
    ungroup() %>%
    select(-month,  -V3)

数据

df <- structure(list(V1 = c(4.59, 4.59, 4.58, 4.52, 4.54, 4.58, 4.09, 
4.5, 4.18, 4.11, 3.54, 4.98), V2 = c("29/12/2000", "01/01/2001", 
"02/01/2001", "03/01/2001", "04/01/2001", "05/01/2001", "26/01/2001", 
"27/01/2001", "28/01/2001", "29/01/2001", "30/01/2001", "31/01/2001"
)), .Names = c("V1", "V2"), class = "data.frame", row.names = c(NA, 
-12L))

【讨论】:

  • 它确实返回了另外 4 个日期......这很奇怪!
  • @HerculesApergis 如果您在顶部查看我的第一个解决方案,它会根据您的示例仅返回一个日期行。
  • @HerculesApergis 我只是在使用一个示例,其中不存在这些日期。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-20
  • 2011-09-26
  • 1970-01-01
  • 2012-08-22
  • 2010-12-03
  • 2010-09-07
相关资源
最近更新 更多