【问题标题】:Adding a column to a data frame by calculating each value to be added通过计算要添加的每个值将列添加到数据框中
【发布时间】:2019-11-27 07:56:52
【问题描述】:

晚上好,

我之前问了一个问题,发现很难实施该解决方案,因此我将以更清晰的方式重新提出。 我有一个问题,我想在股票每日收益的数据框中添加一列。假设它是正态分布的,我想添加一列,其中包含我自己编写的风险值(hist)。 限制是每个观察值都应该分配给我的函数,并且还要接受最后的 249 个观察值。 因此,当计算下一个观测值时,它也应该只取之前 das 的最后 249 个观测值。所以输入值应该随着时间的推移而移动。换句话说,我希望排除 251 天前的值。希望我能很好地解释自己。如果不是,那么代码可能会为我说话:

df<- data.frame(Date=seq(ISOdate(2000,1,1), by = "days", length.out = 500), Returns=rnorm(500))
#function
VaR.hist<- function(x, n=250, hd=20, q=0.05){
  width<-nrow(x)
  NA.x<-na.omit(x)
  quantil<-quantile(NA.x[(width-249):width],probs=q)
  VaR<- quantil*sqrt(hd)%>%
    return()
}
# Run the function on the dataframe
df$VaR<- df$Returns%>%VaR.hist()

 Error in (width - 249):width : argument of length 0 

这是我得到的错误代码,而不是我的新变量... 谢谢!!

【问题讨论】:

  • 您仅使用数字向量 (df$Returns) 调用您的函数。当x 是一个数字向量时,函数的第一行 (nrow(x)) 将返回 NULL
  • 您能否给出前几行的预期输出示例?当您从分布中采样数字时,请使用set.seed,以便我们可以在另一端复制相同的数字。
  • 您好!如果样本预期输出意味着让您了解理想情况下会得出什么数字,那么它将是每日收益损失函数的第 5 个百分位的向量。 IE。 100 天回报系列中的第 5 个最差回报。 Schlegel 先生的解决方案只给了我 1 个重复 500 次的数字,这与我尝试其他东西时得到的结果相同,但从来没有真正成为数字的动态向量……希望它更清楚。

标签: r function dataframe


【解决方案1】:

正如 wibom 在评论中所写的 nrow(x) 不适用于向量。你需要的是length()。此外,最后一行不需要return(),因为如果之前没有早期的return(),R 会自动返回函数的最后一行。

library(dplyr)
df<- data.frame(Date=seq(ISOdate(2000,1,1), by = "days", length.out = 500), Returns=rnorm(500))

#function
VaR.hist <- function(x, n=250, hd=20, q=0.05){
  width <- length(x) # here you need length as x is a vector, nrow only works for data.frames/matrixes
  NA.x <- na.omit(x)
  quantil <- quantile(NA.x[(width-249):width], probs = q)
  quantil*sqrt(hd)
}

# Run the function on the dataframe
df$VaR <- df$Returns %>% VaR.hist()

【讨论】:

  • 嘿!谢谢回答我的问题。我尝试了您的解决方案,它确实会添加一列值。不幸的是,总是相同的数字而不是动态数字......我在上面的评论中更好地解释了自己。仍然感谢您的工作!
【解决方案2】:

要确切地理解你想要做什么有点困难。

我的理解是,您希望计算一个新变量 VarR,它是根据 df$Returns 的当前和之前的 249 次观察计算得出的,对吧?

这是关于你想做的事吗?:

library(tidyverse)
set.seed(42)

df <- tibble(
  Date = seq(ISOdate(2000, 1, 1), by = "days", length.out = 500), 
  Returns=rnorm(500)
)

the_function <- function(i, mydata, hd = 20, q = .05) {
  r <- 
    mydata %>% 
    filter(ridx <= i, ridx > i - 249) %>% 
    pull(Returns)

  quantil <- quantile(r, probs = q)
  VaR <- quantil*sqrt(hd)
}

df <- 
  df %>% 
  mutate(ridx = row_number()) %>% 
  mutate(VaR = map_dbl(ridx, the_function, mydata = .))

如果您正在寻找 base-R 解决方案:

set.seed(42)
df <- data.frame(
  Date = seq(ISOdate(2000, 1, 1), by = "days", length.out = 500), 
  Returns = rnorm(500)
)


a_function <- function(i, mydata, hd = 20, q = .05) {
  r <- mydata$Returns[mydata$ridx <= i & mydata$ridx > (i - 249)] 
  quantil <- quantile(r, probs = q)
  VaR <- quantil*sqrt(hd)
}

df$ridx <- 1:nrow(df) # add index
df$VaR <- sapply(df$ridx, a_function, mydata = df)

【讨论】:

  • 是的,您 100% 理解我,感谢您提供代码示例,这实际上高于我目前的 R 技能水平。我试图运行你的代码,它会返回: Error in ~ridx
  • @Rbitrage - 我已经编辑了上面给出的代码示例,现在应该可以解决问题了。我还添加了一个使用 base R 的建议解决方案。第一个 sn-p 使用 tidyverse 语法和函数。这里有一个很好的介绍:r4ds.had.co.nzpull()dplyr-package中的一个函数,包含在tidyverse中;参见?dplyr::pull)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
  • 2023-01-19
  • 2012-09-04
  • 1970-01-01
相关资源
最近更新 更多