添加数据框中每列的差异和百分比变化?

时间:2012-01-01 01:18:13

标签: r plyr reshape

我希望能够将差异和百分比更改添加到数据框中的每个列。

我能够融化数据并执行计算,但我无法弄清楚如何将它重新组合或重塑。我也怀疑这可以通过 plyr 轻松完成,但diff()返回的n-1行给我带来了问题。

使用包含的数据集:

library(plyr)
library(quantmod)
head(longley)

     GNP.deflator     GNP Unemployed Armed.Forces Population Year Employed
1947         83.0 234.289      235.6        159.0    107.608 1947   60.323
1948         88.5 259.426      232.5        145.6    108.632 1948   61.122
1949         88.2 258.054      368.2        161.6    109.773 1949   60.171
1950         89.5 284.599      335.1        165.0    110.929 1950   61.187
1951         96.2 328.975      209.9        309.9    112.075 1951   63.221
1952         98.1 346.999      193.2        359.4    113.270 1952   63.639

longley.m <- melt(longley, id="Year")
longley.m <- ddply(longley.m, .(variable), transform, valdiff=diff(c(NA, value)), valdelt=Delt(value))

head(longley.m)

  Year     variable value valdiff Delt.1.arithmetic
1 1947 GNP.deflator  83.0      NA                NA
2 1948 GNP.deflator  88.5     5.5       0.066265060
3 1949 GNP.deflator  88.2    -0.3      -0.003389831
4 1950 GNP.deflator  89.5     1.3       0.014739229
5 1951 GNP.deflator  96.2     6.7       0.074860335
6 1952 GNP.deflator  98.1     1.9       0.019750520

(我不知道为什么Delt会自己创建列名,但我放弃了它)

现在,我可以cast(longley.m, Year ~ variable)回到原始数据集,但我希望能够在不同的列中对每个变量进行差异和百分比更改,而无需对每个变量手动执行计算,然后将它重新绑定在一起。我非常有信心我已经尝试了各种演员阵容无济于事......

更新 Joran解决了Delt列命名问题:用as.vector强制它!

3 个答案:

答案 0 :(得分:2)

使用Delt时出现奇怪列名的原因是返回矩阵而不是向量。用as.vector强迫它解决了这个谜。

然而,我怀疑你这太复杂了。您是否有理由不能简单地按年度对数据框进行排序,然后将diffDelt应用于每个列,相应地重命名列,然后cbind将它们组合在一起?< / p>

一些入门代码:

longley.o <- arrange(longley,Year)
apply(longley.o,2,function(x){c(NA,diff(x))})
apply(longley.o,2,Delt)

更完整的版本(无需手动输入列):

longley.o <- arrange(longley,Year)
valdiff <- apply(longley.o,2,function(x){c(NA,diff(x))})
valdelt <- apply(longley.o,2,Delt)

colnames(valdiff) <- paste("valdiff",colnames(valdiff),sep = ".")
colnames(valdelt) <- paste("valdelt",colnames(valdelt),sep = ".")

out <- cbind(longley.o,
             valdiff[,-match("Year",colnames(longley.o))],
             valdelt[,-match("Year",colnames(longley.o))])

答案 1 :(得分:2)

我可能更像@joran。

但是如果你想沿着你所在的道路前进,你可以使用基地R的reshape()来完成旅程:

# Your code
library(plyr)
library(quantmod)
library(reshape)
head(longley)
longley.m <- melt(longley, id="Year")

# My addition
longley.m <- ddply(longley.m, .(variable), transform, 
                   valdiff = diff(c(NA, value)), 
                   valdelt = as.vector(Delt(value)))
reshape(longley.m, idvar="Year", timevar="variable", direction="wide")

答案 2 :(得分:0)

我认为在指标类别中融化和处理的策略是不必要的复杂。如果你想在开始时添加一行NA的数据帧,那么它会与行号相匹配,那么两个替代方案就会将自己称为一个衬里:

as.data.frame( lapply(longley, function(x) c(NA, diff(x))))

或者,如果您知道所有条目都是数字的(通过使用数字函数建议),因此使用apply就可以了,那么这种方法更简单:

apply(longley,2, FUN=function(x) c(NA, diff(x)))

如果你想要这些与Delt结果一起:

cbind(apply(longley,2, FUN=function(x) c(NA, diff(x))), 
      apply(longley,2, Delt) )