R

时间:2016-12-07 09:41:44

标签: r data.table dplyr outer-join

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

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中的转化功能相结合会导致出现奇怪的错误消息“错误:与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

等等。欣赏​​这会留下一些冗余对,但这会让生活更轻松。

提前感谢您的关注。:)

2 个答案:

答案 0 :(得分:3)

通常,如果数据转换不适用于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
..        ...   ...   ...   ...

答案 1 :(得分:2)

我们可以使用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)