【问题标题】:Grouping a data frame in R by month and year using yearmon()使用 yearmon() 按月和年对 R 中的数据框进行分组
【发布时间】:2018-02-24 01:12:36
【问题描述】:

编辑:

我想通了!

df_CloseDelta$YearMonth <- as.yearmon(df_CloseDelta$date)
df_CloseDelta %>%
    group_by(stock, YearMonth) %>%
    summarize(minCloseDelta = min(closeDelta),
              meanCloseDelta = mean(closeDelta),
              maxCloseDelta = max(closeDelta)) -> df_summary_CloseDelta

我创建了以下数据框,其中显示了日期、股票名称以及每只股票的收盘价与前一天相比的百分比差异。

library(quantmod)
library(dplyr)
library(tidyr)
library(ggplot2)
library(zoo)

start <- as.Date("2014-01-01")
end <- as.Date("2017-12-31")
getSymbols(c("AAPL", "AMZN", "FB", "GOOG", "MSFT"),
           from = start, to = end, return.class = "data.frame")

df_wide <- bind_cols(AAPL, AMZN, FB, GOOG, MSFT) %>%
    mutate(date = as.Date(rownames(AAPL))) 

df_long <- df_wide %>%
    gather(key = stock, value = value, - date) %>%
    separate(stock, into = c("stock", "type"))

df_panel <- df_long %>%
    spread(key = type, value = value)

df_CloseDelta <- df_panel %>%
    group_by(stock) %>%
    mutate(closeDelta = 100 * (Close - lag(Close))/lag(Close)) %>%
    select(date, stock, closeDelta) %>%
    filter(!is.na(closeDelta))

我正在尝试按年份和月份对这些条目进行分组(2014 年 1 月 AAPL 收盘价的所有百分比变化,2014 年 1 月 AMZN 收盘价的所有百分比变化等)我正在尝试使用 yearmon() 函数来执行此操作,并认为我可以创建(变异)一个新列,我可以在其中提取年份和月份,然后对数据进行分组,或者只对它进行分组而不创建新列。我能够做到这一点:

as.yearmon(df_CloseDelta$date)

然后返回:

[1] "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014"
[8] "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014"
[15] "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014"
[22] "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014" "Jan 2014"

每个条目以此类推。

然后我尝试将其分组:

df_summary_CloseDelta <- df_CloseDelta %>%
    group_by(as.yearmon(df_CloseDelta$date))

但收到此错误:

Error in mutate_impl(.data, dots) : 
  Column `as.yearmon(df_CloseDelta$date)` must be length 1006 (the group 
size) or one, not 5030

我知道有 1,006 个日期,但鉴于有 5 个股票,因此有 5,030 个条目。我正在尝试对它们进行分组,然后找出每个股票每月和每年的平均值、最小值和最大值。有人可以指出我正确的方向吗?

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    group_by 期望您为其提供变量名称或与数据中的行数相同长度的向量,这将被视为执行分组的一个因素。请参阅下面的示例。

    > btest <- data.frame(a = LETTERS[1:10],
    +                     b = c(1,1,2,2,3,3,4,4,5,5),
    +                     c = c(rep('e',5), rep('f',5)))
    > btest
       a b c
    1  A 1 e
    2  B 1 e
    3  C 2 e
    4  D 2 e
    5  E 3 e
    6  F 3 f
    7  G 4 f
    8  H 4 f
    9  I 5 f
    10 J 5 f
    

    现在我们可以通过以下两种方式之一来计算我们感兴趣的组的总和。传统的方式是使用group_by,然后是我们的变量c

    > btest %>% 
    +   group_by(c) %>% 
    +   summarise(ex = mean(b))
    # A tibble: 2 x 2
      c        ex
      <fct> <dbl>
    1 e      1.80
    2 f      4.20
    

    但是,您的代码认为您正在尝试做的是提供将用于形成分组的逐行值。

    > btest %>% 
    +   group_by(c(1,1,1,1,1,2,2,2,2,2)) %>% 
    +   summarise(ex = mean(b))
    # A tibble: 2 x 2
      `c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)`    ex
                                  <dbl> <dbl>
    1                              1.00  1.80
    2                              2.00  4.20
    

    只是为了让我们清楚应该是什么手段。

    > mean(c(1,1,2,2,3))
    [1] 1.8
    > mean(c(3,4,4,5,5))
    [1] 4.2
    

    您的问题是您需要先添加要分组的列,然后才能按该列进行分组。

    > df_CloseDelta[['date_yearmon']] <- as.yearmon(df_CloseDelta[['date']])
    > 
    > df_CloseDelta %>% 
    +   group_by(date_yearmon, stock) %>% 
    +   summarise(mean_closedelta = mean(closeDelta))
    # A tibble: 240 x 3
    # Groups:   date_yearmon [?]
       date_yearmon  stock mean_closedelta
       <S3: yearmon> <chr>           <dbl>
     1 Jan 2014      AAPL          -0.474 
     2 Jan 2014      AMZN          -0.472 
     3 Jan 2014      FB             0.746 
     4 Jan 2014      GOOG           0.310 
     5 Jan 2014      MSFT           0.104 
     6 Feb 2014      AAPL           0.269 
     7 Feb 2014      AMZN           0.0631
     8 Feb 2014      FB             0.491 
     9 Feb 2014      GOOG           0.159 
    10 Feb 2014      MSFT           0.0713
    # ... with 230 more rows
    

    或者,如果您想在dplyr 中完成所有操作,您可以执行以下操作。

    df_CloseDelta %>%
      mutate(date_yearmon = as.character(as.yearmon(date))) %>%
      group_by(date_yearmon, stock) %>%
      summarise(mean_closedelta = mean(closeDelta))
    

    【讨论】:

      【解决方案2】:

      xts 有 to.monthly 直接转换为每月,因此假设输入 OHLCV 数据位于环境 e 中的一组 xts 对象中,根据最后的注释,我们将转换函数应用于每个这样的对象e(转换为每月、数据框并附加符号),然后 rbinding 生成的数据框给出单个数据。

      sym2df <- function(x, env) cbind(Symbol = x, fortify.zoo(to.monthly(env[[x]], name = "")))
      do.call("rbind", lapply(ls(e), sym2df, env = e))
      

      注意

      将股票数据导入环境e:

      library(quantmod)
      
      start <- "2014-01-01"
      end <- "2017-12-31"
      syms <- c("AAPL", "AMZN", "FB", "GOOG", "MSFT")
      getSymbols(syms, from = start, to = end, env = e <- new.env())
      

      【讨论】:

        猜你喜欢
        • 2019-04-17
        • 2020-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多