【问题标题】:Add difference and percent change of every column in a data frame?添加数据框中每一列的差异和百分比变化?
【发布时间】:2012-01-31 06:14:42
【问题描述】:

我希望能够将差异和百分比变化添加到数据框中的每一列。

我能够将数据融合并执行计算,但我不知道如何将其重新组合或重新组合在一起。我也暗中怀疑这很容易用 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 强制它!

【问题讨论】:

  • 有吗?我的问题更多是关于对每一列执行相同的操作并将其放回数据框中。我在那里没有看到解决方案。
  • 我想我不明白困难的根源。我知道我可以做些什么来取消投票。

标签: r plyr reshape


【解决方案1】:

我可能会更像@joran。

但如果你想继续沿着你之前的道路前进,你可以使用 base 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")

【讨论】:

  • 我认为这正是我想要的。重塑对我来说不是点击。谢谢!
  • 嘿。很多人都有 reshape 的经验。
【解决方案2】:

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

但是,我怀疑你把这弄得太复杂了。您是否有理由不能简单地按年份对数据框进行排序,然后将diffDelt 应用于每一列,适当地重命名列,然后将它们一起cbind

一些入门代码:

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

【讨论】:

  • 感谢您解开第一个谜团!虽然我确实倾向于把事情复杂化,但在这种情况下,我觉得我至少走在正确的道路上。简单地在每列上进行 diff 和 Delt 的问题(在我融化它之前)是我希望每个变量每年都得到它。我必须在您的解决方案中明确输入每一列。我的实际问题在大约十几个不同的数据框中有 20 多列,所以我正在寻找简单的出路。
  • @Totovader 我并没有真正遵循你的推理。如果您更愿意使用 reshape,那么 Josh 可以满足您的需求。我上面的更新应该给出与他的答案相同的结果。
  • 我知道你要去哪里了,现在 - 你的 cbind 部分的 match 部分对我来说是陌生的,所以这将是一些额外的步骤。
  • 在数据帧上使用应用时要小心——它会强制转换为矩阵。
【解决方案3】:

我认为在指标类别内进行融化和处理的策略过于复杂。如果您想要一个在开始时添加一行 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) )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-23
    • 2017-09-02
    • 1970-01-01
    • 2021-12-26
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    相关资源
    最近更新 更多