在`dplyr :: mutate()`中引用特定值

时间:2015-06-11 18:36:15

标签: r dplyr

我有以下代码:

library(dplyr)
library(quantmod)

# inflation data
getSymbols("CPIAUCSL", src='FRED')
avg.cpi <- apply.yearly(CPIAUCSL, mean)
cf <- avg.cpi/as.numeric(avg.cpi['1991']) # using 1991 as the base year
cf <- as.data.frame(cf)
cf$year <- rownames(cf)
cf <- tail(cf, 25)
rownames(cf) <- NULL
cf$year <- lapply(cf$year, function(x) as.numeric(head(unlist(strsplit(x, "-")), 1)))
rm(CPIAUCSL)
# end of inflation data get

tmp <- data.frame(year=c(rep(1991,2), rep(1992,2)), price=c(12.03, 12.98, 14.05, 14.58))
tmp %>% mutate(infl.price = price / cf[cf$year == year, ]$CPIAUCSL)

我想得到以下结果:

year price
1991 12.03
1991 12.98
1992 13.64
1992 14.16

但是我收到了一个错误:

Warning message:
In cf$year == tmp$year :
  longer object length is not a multiple of shorter object length

使用%in%会产生错误的结果。

2 个答案:

答案 0 :(得分:4)

我认为在您尝试变异之前,将CPIAUCSL中的cf列加入tmp可能会更容易:

cf$year = as.numeric(cf$year)
tmp = tmp %>% inner_join(cf, by = "year") %>% mutate(infl.price = price / CPIAUCSL)

答案 1 :(得分:3)

您的cf结构是一个不友好的列表列表。

有更好的表现
cf$year <- sapply(cf$year, function(x) as.numeric(head(unlist(strsplit(x, "-")), 1)))

至少返回一个简单的向量。

此外,对于此类操作,子集化运算符[]未正确向量化。 mutate()函数不会遍历行,它一次对整个列进行操作。当你这样做

cf[cf$year == year, ]$CPIAUCSL

不只有一个year值,mutate正在尝试同时执行所有操作。

最好合适地合并数据,然后进行变异。这基本上与你试图在你的版本中进行的伪合并做同样的事情。

你可以做到

tmp %>% left_join(cf) %>% 
    mutate(infl.price = price / CPIAUCSL) %>% 
    select(-CPIAUCSL)

获取

  year price infl.price
1 1991 12.03   12.03000
2 1991 12.98   12.98000
3 1992 14.05   13.63527
4 1992 14.58   14.14962