【问题标题】:Calculate mean prices of every quarter between a given startdate and enddate?计算给定开始日期和结束日期之间每个季度的平均价格?
【发布时间】:2016-09-13 09:53:47
【问题描述】:

我还需要你的帮助,因为我自己没有得到正确的结果。

我的数据看起来像这样:

product startdate    enddate     city     cost   double
  1    1999-01-03  2001-02-01   Boston      8       0
  2    2000-07-06  2001-11-24   New York   10,5     0
...

我想要的是一个表格,显示平均成本除以城市和季度。

到目前为止我做了什么:

df <- read_csv2("mydata.csv")

#subset data
double <- df$double
df2 <- subset(df,double==0)


#date class
startdate <- strptime(df2$startdate,format="%Y-%m-%d")

library(zoo)
quarter <- as.yearqtr(startdate,"%Y-%m-%d")


table <- tapply(cost,list(df2$city,quarter),mean)

我得到的表格可能是这样的:

City       2011 Q1 2011 Q2 2011 Q3
New York     10     11,2    11,7
Boston       9       9,5    9,9

我的问题是我有一个开始日期和一个结束日期。该表向我显示了取决于开始日期的季度。 我现在想得到同一张桌子,但宿舍应该包括结束日期。这意味着:如果 startdate 是 2006-01-01 并且 enddate 是 2006-08-01 我的项目在 2006 Q1、2006 Q2、2006 Q3 季度在线。 我的商品的价格一直是一样的,但是当我计算每个季度的平均价格时,价格应该包含在产品上线的每个季度中。

我所做的是更改结束日期的类别:

#enddate , date class
today <- Sys.Date()
df2[["enddate"]][is.na(df2[["enddate"]])] <- today
enddate <- strptime(df2$enddate,format="%Y-%m-%d")

现在我尝试了几件事,例如处理日期间隔和截止日期,但这根本不起作用。

感谢您的任何提示!

【问题讨论】:

    标签: r date date-range


    【解决方案1】:

    您的完整解决方案可能如下所示。我用过data.table。

    在data.table中加载数据

    library(data.table)
    d <- read.csv("Products.csv")
    D <- as.data.table(d)
    

    条件数据以适当地处理日期并计算财政季度。

    # Condition data
    #   Format date columns to Date objects
    D[, ':=' (Date.Start = as.Date(Date.Start, format="%d-%b-%y"),
      Date.End = as.Date(Date.End, format="%d-%b-%y"))][]
    #   Compute the no. of quarters from start, end dates
    #     Use:
    #       getSeriesV() for dates every quarter given start and end dates
    #       getQuarterV() for the fiscal quarter given a date
    Quarters <- D[, .(getSeriesV(Date.Start, Date.End))]
    Quarters <- lapply(Quarters$V1, function(x) unique(getQuarterV(x)))
    

    以长格式扩展 data.table 以包含有关财政季度的信息。

    Repeats <- sapply(Quarters, length)
    Names <- D[, rownames(.SD)]
    de <-  d[rep(Names, Repeats),]
    De <- as.data.table(de)
    De[, ':=' (Date.Start = as.Date(Date.Start, format="%d-%b-%y"),
               Date.End = as.Date(Date.End, format="%d-%b-%y"))][]
    De[, Quarters := unlist(Quarters)]
    

    分析汇总数据。

    De[, .(Avg = mean(Cost)), by=c('Product', 'City', 'Quarters')]
    

    我从数据开始

    Product,Date.Start,Date.End,City,Cost
    Apple,1-Jan-16,1-Aug-16,Bangalore,150
    Tomato,1-Dec-15,15-Jan-16,Pune,30
    Apple,1-Nov-15,1-Jun-16,Bangalore,155
    Tomato,1-Jun-16,1-Dec-16,Bangalore,45
    Tomato,1-Oct-16,1-Nov-16,Pune,15
    

    【讨论】:

    • 非常感谢您的回答,帮助我了解了我需要做什么。不幸的是,我在使用 seq 函数时出错。我所做的是将我的日期列格式化为日期对象。当我想执行下一步时: Quarters D$Date.Start [1] "2016-06-18" "2013-06-30" "2016-06-28" “2016-06-24” “2014-01-14” ....
    • Tim,你有没有对getSeries() 函数进行矢量化以获得getSeriesV() 函数?通过getSeriesV &lt;- Vectorize(getSeries) 执行此操作。请看看这是否有效。
    • 我的错,完美!执行下一步时仍然遇到问题: de str(de) 类“tbl_df”、“tbl”和“data.frame”:4036 obs。 183 个变量: $ city : chr NA NA NA NA NA NA NA NA NA NA ... $ enddate :日期,格式:NA NA ... $ startdate :日期,格式:NA NA ...
    • 我已经在 github 上发布了我的示例代码:github.com/sunbee/R-How-To/blob/master/…。数据位于文件“Products.csv”中。请看看这是否有帮助。干杯!
    • 您能检查一下NamesRepeats 中的内容吗?这些应该是相同长度的向量。想法是将数据表扩展为长格式,使用行名称按日期跨越的季度数重复行。
    【解决方案2】:

    一种策略是使用会计年度季度的附加信息(即列)以长格式扩展您的表格。然后,您可以使用枢轴以您想要的方式进行汇总。

    要获取年份和季度,请使用类似

    的函数
    getQuarter <- function(x, first=0, prefix="Q") {
      # x:      Date object 
      # first:  Jan is 0
      # prefix: Affix symbol for quarter, default 'Q' 
      d <- as.POSIXlt(x);
      q <- floor((d$mon-first+1)/3.03)
      q <- paste0(d$year+1900,'-',prefix,q+1, collapse="")
      q
    }
    

    试试看:

    start <- as.Date("01-01-16", format="%d-%m-%y")
    end <- as.Date("01-09-16", format="%d-%m-%y")
    getQuarter(start)   # "2016-Q1"
    getQuarter(end)     # "2016-Q3"
    

    然后像这样矢量化它。

    getQuarterV <- Vectorize(getQuarter)
    getQuarterV(c(start, end))   # "2016-Q1" "2016-Q3"
    

    要获取开始日期和结束日期之间的所有季度,请使用类似的函数

    getSeries <- function(start, end) {
      # start:  Date object
      # end:    Date object
      s <- seq(from=start, to=end, by="3 months")
      s <- c(s, end)
      unique(s)
    }
    

    试试看:

    getSeries(start, end)     # "2016-01-01" "2016-04-01" "2016-07-01" ..
    getSeries(start, start)   # "2016-01-01"
    

    现在把它放在一起得到两个日期之间的所有季度。

    unique(getQuarterV(getSeries(start, end)))   # "2016-Q1" "2016-Q2" "2016-Q3"
    

    您现在可以继续将此数据与您的原始数据集成并提取您需要的摘要。

    【讨论】:

      猜你喜欢
      • 2011-03-27
      • 1970-01-01
      • 2012-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-05
      • 2010-12-02
      • 1970-01-01
      相关资源
      最近更新 更多