【问题标题】:R - Extracting more than one row from a data frame based on an indicator in another columnR - 根据另一列中的指标从数据框中提取多行
【发布时间】:2018-02-13 16:44:36
【问题描述】:

我有一个关于根据指标从 R 中的 data.frame 中提取多个值的问题

我有一个如下所示的 data.frame (df)

 ROW        COMPANY       PRICE      DATE          EVENT
  1         APPLE         1.50       Jan02           0
  2         APPLE         1.70       Feb02           1
  3         APPLE         1.65       Mar02           0
  4         APPLE         1.20       Apr02           0
  5         APPLE         1.30       May02           0
  6         APPLE         1.14       Jun02           0
  7         APPLE         1.10       Jul02           0
     .         .           .           .             .
     .         .           .           .             .
  349.997   MICROSOFT     0.80       Sep16           0
  349.998   MICROSOFT     0.65       Oct16           0
  349.999   MICROSOFT     1.10       Nov16           1
  350.000   MICROSOFT     0.90       Dez16           0

如您所见,我有一个大型 data.frame,其中包含各种公司及其在给定日期的股价。另外我有一个事件列(只有 0 和 1 作为值)。值 1 表示在给定日期发生了特定事件(例如股东大会)。在 350.000 行中,我有 2.500 个事件(这意味着 Column Event 有 2.500 个 1 和 347.500 个零)。

现在我的目标是围绕特定事件分析股票价格(例如分析事件发生前 10 个月和事件发生后 15 个月的股票价格)。现在来看看我是如何进行的以及我目前被困在哪里。

首先,我必须根据我的公司拆分我的 data.frame,因为如果我在我的观察期(2002-2016 年)之外,我需要获得 NA。例如如果苹果在 nov16 有一个事件,我需要在 2 个月后得到价格,我应该得到一个 NA(因为它超出了我的观察期),但在未拆分的 data.frame 中,我会得到下一个的价格从 Jan02 开始的公司。

list<-split(df, f=df$COMPANY)

现在是我卡住的部分。我需要为每个公司提取活动日之前的 10 个价格和活动日之后的 15 个价格

我试图创建的输出看起来像(注意:“?”=这些值存在,但它们没有显示在上面的示例 df 中)

     Event 1 (Apple)              Event 2500   (Microsoft)
-10      NA               ...         ?
 -9      NA               ...         ?
  .      .
  0     1.70              ...        1.10
  .      .
+15      ?                ...         NA

抱歉,如果不详细说明,真的很难正确解释我的问题,但我希望我能在某种程度上说清楚。

感谢您的帮助:)

【问题讨论】:

    标签: r dataframe row indicator


    【解决方案1】:

    这可以通过dplyrtidyr 包来完成,尽管它有点复杂。这是一个小得多的数据集的要点:

    library(dplyr)
    library(tidyr)
    df <- readr::read_csv("COMPANY,PRICE,DATE,EVENT
    APPLE,1.50,2002/01/01,0
    APPLE,1.70,2002/02/01,1
    APPLE,1.65,2002/03/01,0
    APPLE,1.20,2002/04/01,0
    MICROSOFT,2.50,2002/01/01,0
    MICROSOFT,2.70,2002/02/01,0
    MICROSOFT,2.65,2002/02/01,1
    MICROSOFT,2.20,2002/03/01,0")
    df
    # A tibble: 8 x 4
    COMPANY PRICE       DATE EVENT
    <chr> <dbl>     <date> <int>
    1     APPLE  1.50 2002-01-01     0
    2     APPLE  1.70 2002-02-01     1
    3     APPLE  1.65 2002-03-01     0
    4     APPLE  1.20 2002-04-01     0
    5 MICROSOFT  2.50 2002-01-01     0
    6 MICROSOFT  2.70 2002-02-01     0
    7 MICROSOFT  2.65 2002-02-01     1
    8 MICROSOFT  2.20 2002-03-01     0
    

    首先,我们需要构建一些滞后和领先。如果您想要更多活动前/后天数,则必须在此处添加更多列。

    with_lags <- df %>% 
      group_by(COMPANY) %>% 
      mutate(
        lag_01    = lag(PRICE,  n = 1, order_by = DATE)
        , lag_02  = lag(PRICE,  n = 2, order_by = DATE)
        , lag_00  = lag(PRICE,  n = 0, order_by = DATE)
        , lead_01 = lead(PRICE, n = 1, order_by = DATE)
        , lead_02 = lead(PRICE, n = 2, order_by = DATE)
      )
    with_lags
    # A tibble: 8 x 9
    # Groups:   COMPANY [2]
    COMPANY PRICE       DATE EVENT lag_01 lag_02 lag_00 lead_01 lead_02
    <chr> <dbl>     <date> <int>  <dbl>  <dbl>  <dbl>   <dbl>   <dbl>
    1     APPLE  1.50 2002-01-01     0     NA     NA   1.50    1.70    1.65
    2     APPLE  1.70 2002-02-01     1   1.50     NA   1.70    1.65    1.20
    3     APPLE  1.65 2002-03-01     0   1.70    1.5   1.65    1.20      NA
    4     APPLE  1.20 2002-04-01     0   1.65    1.7   1.20      NA      NA
    5 MICROSOFT  2.50 2002-01-01     0     NA     NA   2.50    2.70    2.65
    6 MICROSOFT  2.70 2002-02-01     0   2.50     NA   2.70    2.65    2.20
    7 MICROSOFT  2.65 2002-02-01     1   2.70    2.5   2.65    2.20      NA
    8 MICROSOFT  2.20 2002-03-01     0   2.65    2.7   2.20      NA      NA
    

    现在我们只保留 EVENT 为 1 的行,并将数据重新排列为长格式。请注意,您必须编辑调用 gather() 函数的行以反映您在上面构建的滞后/领先列的列表:

    long_form <- with_lags %>%
      filter(EVENT == 1) %>% 
      select(-PRICE, -EVENT, -DATE) %>% 
      gather(period, price, lag_01:lead_02) %>% 
      separate(period, c("lag_or_lead", "lag_order")) %>% 
      mutate(
        lag_order = ifelse(lag_or_lead == "lag", 
                           -1 * as.numeric(lag_order),
                           as.numeric(lag_order)) 
      ) %>% 
      select(-lag_or_lead) %>% 
      arrange(COMPANY, lag_order)
    long_form
    # A tibble: 10 x 3
    # Groups:   COMPANY [2]
    COMPANY lag_order price
    <chr>     <dbl> <dbl>
    1      APPLE        -2    NA
    2      APPLE        -1  1.50
    3      APPLE         0  1.70
    4      APPLE         1  1.65
    5      APPLE         2  1.20
    6  MICROSOFT        -2  2.50
    7  MICROSOFT        -1  2.70
    8  MICROSOFT         0  2.65
    9  MICROSOFT         1  2.20
    10 MICROSOFT         2    NA
    

    如果您需要宽格式,则可以使用tidyr 包中的spread() 将公司移动到列中。

    【讨论】:

      【解决方案2】:

      我可能会因为建议(震惊恐怖)在基础 R 中使用循环来执行此操作而被击落,但恕我直言,易于理解和编辑的代码通常是更简洁但不易理解的编程的更可取的选择。只有 2500 个事件,我认为它应该足够快。如果您可以将解决方案的速度与您的真实数据进行比较,会很有趣吗?

      set.seed(0)
      SP <- data.frame(Company = c(rep_len("Apple", 50), 
                                   rep_len("Microsoft", 50)),
                       Price = round(runif(100, 1, 2), 2),
                       Date = rep(seq.Date(from = as.Date("2002-01-01"), 
                                         length.out = 50, by = "month"),
                                          2),
                       Event = rbinom(100, 1, 0.05),
                       stringsAsFactors = FALSE)
      
      Event <- which(SP$Event %in% 1)
      resultFrame <- data.frame(Period = (-10):15)
      for (i in Event){
        Stock <- SP$Company[i]
        eventTime <- format(SP$Date[i], "%b-%Y")
        stockWin <- (i - 10):(i + 15)
        stockWin[stockWin <= 0 | stockWin > nrow(SP)] <- NA
        stockWin[!(SP$Company[stockWin] %in% Stock)] <- NA
        priceWin <- SP[stockWin, "Price"]
        eventName <- paste("Event", eventTime, Stock, sep=".")
        resultFrame <- data.frame(resultFrame, priceWin)
        names(resultFrame)[ncol(resultFrame)] <- eventName
      }
      

      【讨论】:

      • 抱歉花了同样的时间完成我的工作,但感谢它完美地工作
      猜你喜欢
      • 1970-01-01
      • 2016-12-10
      • 2015-11-21
      • 2020-11-13
      • 1970-01-01
      • 2022-06-24
      • 2021-11-27
      • 2020-09-08
      • 1970-01-01
      相关资源
      最近更新 更多