使用yearmon()按月和按年对R中的数据框进行分组

时间:2018-02-24 01:12:37

标签: r dplyr

修改

我明白了!

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

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

enter image description here

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,030个条目,因为有5个股票。我正在尝试对它们进行分组,然后找出每个库存的每月和每年的平均值,最小值和最大值。有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分: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))

答案 1 :(得分:0)

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())