【问题标题】:How to merge two dataframes on a column that needs to be 3 months ahead without using for loop如何在不使用for循环的情况下合并需要提前3个月的列上的两个数据框
【发布时间】:2023-03-14 17:06:01
【问题描述】:

我有在 R 中对列值在两个数据帧之间匹配的数据帧使用 inner_join 函数的经验。但是,我有一个数据框包含 2007-2014 年每只股票每个月的平均股价,另一个数据框包含 2007-2014 年每只股票的财务比率,并显示每家公司的财政年度结束月份。问题是,一家公司的财务比率要到 3 个月后发布 10K 才能报告。因此,我想将每家公司的财务比率与其合适的股票价格相匹配,即 3 个月后。

比率DF:

Symbol Month Year 10KRatio1 10KRatio2 ... 10KRatioN
 FLWS    6   2007   100        200    ...    1000
 ACAD    12  2007   500        600    ...    2000

StockPriceDF:

Company Year Month MeanPrice
 FLWS   2007  1      6.32
   .     .    .       .
   .     .    .       .
   .     .    .       .
 FLWS   2007  9     10.995
   .     .    .       .
   .     .    .       .
   .     .    .       .
 FLWS   2014  12    17.92
   .     .    .       .
 ACAD   2007  1      7.5
   .     .    .       .
   .     .    .       .
   .     .    .       .
 ACAD   2008  3      8.64
   .     .    .       .
   .     .    .       .

所需的DF:

Symbol Month Year 10KRatio1 10KRatio2 ... 10KRatioN MeanPrice
 FLWS   9    2007   100       200           1000      10.995
 ACAD   3    2008   500       600           2000       8.64

我正在考虑使用 for 循环来检查 RatioDF 月份是否为 10-12 月份,然后将其与明年的 1-3 月份匹配以获取适当的符号/公司,但我认为计算可能也需要因为这些年库存很多,月价格也很多。

【问题讨论】:

    标签: r date merge inner-join


    【解决方案1】:

    lubridatedata.tabledplyr 的可能解决方案。

    1) 带有 data.table:

    # load packages
    library(lubridate)
    library(data.table)
    
    # convert both dataframes to data.table's and add a 'date'-variable
    setDT(d1)[, date := as.IDate(sprintf('%s-%02d-01',Year,Month))][]
    
    # idem + substract 3 months with lubridate's '%m-%` function
    setDT(d2)[, date := as.IDate(sprintf('%s-%02d-01',Year,Month)) %m-% months(3)][]
    
    # join d1 with d2 and update d1 by reference
    d1[d2, on = .(Symbol = Company, date), MeanPrice := MeanPrice][]
    

    给出:

       Symbol Month Year 10KRatio1 10KRatio2       date MeanPrice
    1:   FLWS     6 2007       100       200 2007-06-01    10.995
    2:   ACAD    12 2007       500       600 2007-12-01     8.640
    

    另一种连接方法可能是:

    d1[d2[, .(Company, date, MeanPrice)], on = .(Symbol = Company, date), nomatch = 0L][]
    

    2) 使用 dplyr:

    # load packages
    library(lubridate)
    library(dplyr)
    
    # add a 'date'-variable to 'd1'
    # add a 'date'-variable to 'd2' and substract 3 months
    # from that  with lubridate's '%m-%` function
    # select only 'Company', 'date' and 'MeanPrice' from 'd2'
    # join 'd1' with 'd2'
    
    d1 %>% 
      mutate(date = as.Date(sprintf('%s-%02d-01',Year,Month))) %>% 
      left_join(., d2 %>% 
                  mutate(date = as.Date(sprintf('%s-%02d-01',Year,Month)) %m-% months(3)) %>% 
                  select(Company, date, MeanPrice),
                by = c('Symbol' = 'Company', 'date'))
    

    给出相同的结果:

      Symbol Month Year 10KRatio1 10KRatio2       date MeanPrice
    1   FLWS     6 2007       100       200 2007-06-01    10.995
    2   ACAD    12 2007       500       600 2007-12-01     8.640
    

    使用过的数据:

    d1 <- structure(list(Symbol = c("FLWS", "ACAD"), 
                         Month = c(6L, 12L), 
                         Year = c(2007L, 2007L), 
                         `10KRatio1` = c(100L, 500L), 
                         `10KRatio2` = c(200L, 600L)), 
                    .Names = c("Symbol", "Month", "Year", "10KRatio1", "10KRatio2"), class = "data.frame", row.names = c(NA, -2L))
    
    d2 <- structure(list(Company = c("FLWS", "FLWS", "FLWS", "ACAD", "ACAD"),
                         Year = c(2007L, 2007L, 2014L, 2007L, 2008L),
                         Month = c(1L, 9L, 12L, 1L, 3L),
                         MeanPrice = c(6.32, 10.995, 17.92, 7.5, 8.64)),
                    .Names = c("Company", "Year", "Month", "MeanPrice"), class = "data.frame", row.names = c(NA, -5L))
    

    【讨论】:

      猜你喜欢
      • 2023-03-19
      • 2023-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-30
      • 1970-01-01
      相关资源
      最近更新 更多