R中分组的外部操作

Outer operation by group in R

我的问题涉及计算每个时期产品之间的价格差异。使用以下示例数据

product = c('A','A','A','B','B','B','C','C','C')
date = as.Date(c('2016-09-12','2016-09-19', '2016-09-26','2016-09-12','2016-09-19', '2016-09-26', '2016-09-12','2016-09-19', '2016-09-26'))
price = as.numeric(c(17, 14.7, 15, 14.69, 14.64, 14.63, 13.15, 13.15, 13.15))

df <- data.frame(product, date, price)

挑战在于分组,如果没有分组,对外部函数的简单调用就可以解决问题。

melt(outer(df$price, df$price, "-"))

然而,将其与 dplyr 中的转换函数结合使用会导致看起来很奇怪的错误消息 "Error: not compatible with STRSXP"。在线评论表明这可能是由于包中的错误。

所以我想知道是否有人对替代方法有巧妙的建议。

理想情况下,我也在寻找以下几行的输出。

Var1 Var2 Date          value
A    A    '2016-09-12'  0.00
A    B    '2016-09-12'  2.31
A    C    '2016-09-12'  3.85
B    A    '2016-09-12' -2.31
B    B    '2016-09-12'  0.00
B    C    '2016-09-12'  1.54
C    A    '2016-09-12' -3.85
C    B    '2016-09-12' -1.54
C    C    '2016-09-12'  0.00
A    A    '2016-09-19'  0.00
A    B    '2016-09-19'  0.06
A    C    '2016-09-19'  1.55

等等。感谢这会留下一些多余的对,但这会让以后的生活更轻松。

提前感谢您的关注。:)

一般来说,如果数据转换不适用于 mutate/transform,您可以尝试 do:

> library(dplyr)
> df %>% 
   group_by(date) %>% 
   do(reshape2::melt(outer(.$price, .$price, "-")))

Source: local data frame [27 x 4]
Groups: date [3]

         date  Var1  Var2 value
       (date) (int) (int) (dbl)
1  2016-09-12     1     1  0.00
2  2016-09-12     2     1 -2.31
3  2016-09-12     3     1 -3.85
4  2016-09-12     1     2  2.31
5  2016-09-12     2     2  0.00
6  2016-09-12     3     2 -1.54
7  2016-09-12     1     3  3.85
8  2016-09-12     2     3  1.54
9  2016-09-12     3     3  0.00
10 2016-09-19     1     1  0.00
..        ...   ...   ...   ...

我们可以使用data.table

library(data.table)
res <- setDT(df)[, melt(outer(price, price, "-")) , by = date]
res[, c("Var1", "Var2") := lapply(.SD, function(x)
                unique(df$product)[x]),.SDcols = Var1:Var2]

head(res)
#         date Var1 Var2 value
#1: 2016-09-12    A    A  0.00
#2: 2016-09-12    B    A -2.31
#3: 2016-09-12    C    A -3.85
#4: 2016-09-12    A    B  2.31
#5: 2016-09-12    B    B  0.00
#6: 2016-09-12    C    B -1.54

一个选项使用tidyr/dplyr

library(tidyr)
library(dplyr)
df %>%
   group_by(date) %>% 
   expand(price, price2=price) %>% 
   mutate(value = price-price2)