【问题标题】:How can I populate the rows of an R data frame, in which each row represents a day, with a single common value for each day of a year?如何填充 R 数据框的行,其中每一行代表一天,一年中的每一天都有一个共同值?
【发布时间】:2012-01-22 14:23:48
【问题描述】:

R:我如何填充数据框的行,其中每一行代表一天,每年都有一个共同的值?

我有一个数据框,其中包含一个日期列、一个价格列以及从这两列派生的各种其他列。其中一列计算给定年份中每一天的价格从该年初开始的百分比变化(这与之前的问题有关)。

我想添加一个列,其中包含给定年份的每一天,该年全年价格的百分比变化。因此,如果价格从 2009 年的第一天到最后一天上涨 10%,则 2009 年所有天数的列应保持 10%(或 0.1)的值。如果价格在 2010 年的第一天和最后一天之间下跌了 2%,则 2010 年每一天的列应保持值 -0.02,依此类推。

我目前的代码是:

require(lubridate)
require(plyr)
# generate data
set.seed(12345)
df <- data.frame(date=seq(as.Date("2009/1/1"), by="day", length.out=1115),price=runif(1115, min=100, max=200))
# remove weekend days
df <- df[!(weekdays(as.Date(df$date)) %in% c('Saturday','Sunday')),]
# add some columns for later
df$year <- as.numeric(format(as.Date(df$date), format="%Y"))
df$month <- as.numeric(format(as.Date(df$date), format="%m"))
df$day <- as.numeric(format(as.Date(df$date), format="%d"))
df$daythisyear <- as.numeric(format(as.Date(df$date), format="%j"))
df <- transform(df, doy = as.Date(paste(2000, month, day, sep="/")))
df <- ddply(df, .(year), transform, pctchg = ((price/price[1])-1))

我意识到我可以通过使用另一个数据框来获得年度(同比)变化,如下所示:

df.yr <- ddply(df, .(year), function(x) (x[nrow(x),2]/x[1,2])-1)

...但是我不知道如何将年份的数字添加到现有数据框中的列中,特别是考虑到(如果您使用 4 年的数据)只有 4 行,每年一个,而用于派生这 4 行的每日数据的数据框中大约有 800 个 - 你会得到不匹配。

使用 for 循环从数据框的最后一行开始并向上移动 daythisyear 列来实现这一点很简单(如果当前行上的 daythisyear 大于下面行上的 daythisyear,则您可以更改年,因此从该行中获取新值以在要添加的列中使用等)。尽管如此,我确信必须有一种使用 apply 函数或 ddply 的 R-口语化方法,到目前为止我一直刻意避免处理。所以我的问题是:

问。如何计算列值的年度变化,然后将该值作为新列插入该年的每一行?

【问题讨论】:

  • 不确定我是否理解你的问题,但如果我理解了,head( merge( df, df.yr, by = "year" ) ) 可能会给你想要的吗?
  • vaettchen,感谢您的建议。这似乎也有效,并且向我展示了我以前没有考虑过的“合并”的一面。

标签: r vectorization plyr


【解决方案1】:

我还没有转换为 ddply 用户,当它是明显的解决方案时,我更喜欢使用 ave。我怀疑这段代码会翻译成:

 df$pctYrChng <- ave(df$price, df$year, FUN=function(x) tail(x,1)/head(x,1) - 1)
 unique(df$pctYrChng)
#[1] -0.03259032 -0.05781901  0.35932519  0.04246669

【讨论】:

  • 这似乎确实可以按要求工作,而且非常简单。我隐约知道'ave',但我自己没有使用它。如果它可以在基础 R 中轻松完成,那么我觉得没有必要去别处寻找!谢谢,丹
  • 我不确定我是否知道您是否想要 YTD 更改,或者您是否想要从 day.one 到 day.last 的更改。我给了你第二个选项的解决方案,但第一个选项的解决方案只需要用 x 替换 tail(x,1)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-29
  • 1970-01-01
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多