在具有缺失值的列上使用 sapply
Using sapply on column with missing values
我大致了解应用函数系列的作用,但我在使用它根据另一列缺失值来改变新列时遇到了问题。我可以使用 for 循环完成我的任务,但我想通过使用应用类型函数来加快性能
假设我有一个从今天开始到几年后结束的指数时间序列。我的原始索引仅在最初几年存在。然后,我想在接下来的几年中使用假定的百分比变化(假设为 10%)人为地扩展这些索引,并将其存储为新列。
这是我的示例数据集:
data <- data.frame(
date = seq.Date(as.Date("2019-01-01"),as.Date("2021-01-01"),"3 months"),
index = c(1,1.2,1.4,1.5,1.6,1.7,NA,NA,NA)
)
我现在可以使用 for 循环创建一个新列 index2:
data$index2 <- 1
for (i in 1:nrow(data)) {
if (!is.na(data$index[i])) {
data$index2[i] = data$index[i]
}
else {
data$index2[i] = data$index2[i-1]*1.1
}
}
但是,我不知道如何使用应用函数来完成此操作。再次感谢您的任何建议。
如果我没有理解错的话,这似乎是lag
的工作:
library(dplyr)
data %>% mutate(index2 = if_else(!is.na(index), index, lag(index) * 1.1))
# date index index2
#1 2019-01-01 1.0 1.00
#2 2019-04-01 1.2 1.20
#3 2019-07-01 1.4 1.40
#4 2019-10-01 1.5 1.50
#5 2020-01-01 1.6 1.60
#6 2020-04-01 1.7 1.70
#7 2020-07-01 NA 1.87
#8 2020-10-01 NA NA
#9 2021-01-01 NA NA
这将重现您的预期输出(即仅替换第一个 NA
);我可能误解了您的问题陈述,但我不明白 *apply
与此有什么关系。
您可以实现这样的sapply
位置
transform(data, index2 = c(index[1], sapply(seq_along(index)[-1], function(i)
if (!is.na(index[i])) index[i] else index[i - 1] * 1.1)))
# date index index2
#1 2019-01-01 1.0 1.00
#2 2019-04-01 1.2 1.20
#3 2019-07-01 1.4 1.40
#4 2019-10-01 1.5 1.50
#5 2020-01-01 1.6 1.60
#6 2020-04-01 1.7 1.70
#7 2020-07-01 NA 1.87
#8 2020-10-01 NA NA
#9 2021-01-01 NA NA
但这不是很漂亮。
在您修正错字后,问题陈述略有变化,我们需要 cumprod
data %>%
mutate(index2 = if_else(
!is.na(index),
index,
index[which.max(index)] * cumprod(c(rep(1.0, sum(!is.na(index))), rep(1.1, sum(is.na(index)))))))
# date index index2
#1 2019-01-01 1.0 1.0000
#2 2019-04-01 1.2 1.2000
#3 2019-07-01 1.4 1.4000
#4 2019-10-01 1.5 1.5000
#5 2020-01-01 1.6 1.6000
#6 2020-04-01 1.7 1.7000
#7 2020-07-01 NA 1.8700
#8 2020-10-01 NA 2.0570
#9 2021-01-01 NA 2.2627
我大致了解应用函数系列的作用,但我在使用它根据另一列缺失值来改变新列时遇到了问题。我可以使用 for 循环完成我的任务,但我想通过使用应用类型函数来加快性能
假设我有一个从今天开始到几年后结束的指数时间序列。我的原始索引仅在最初几年存在。然后,我想在接下来的几年中使用假定的百分比变化(假设为 10%)人为地扩展这些索引,并将其存储为新列。
这是我的示例数据集:
data <- data.frame(
date = seq.Date(as.Date("2019-01-01"),as.Date("2021-01-01"),"3 months"),
index = c(1,1.2,1.4,1.5,1.6,1.7,NA,NA,NA)
)
我现在可以使用 for 循环创建一个新列 index2:
data$index2 <- 1
for (i in 1:nrow(data)) {
if (!is.na(data$index[i])) {
data$index2[i] = data$index[i]
}
else {
data$index2[i] = data$index2[i-1]*1.1
}
}
但是,我不知道如何使用应用函数来完成此操作。再次感谢您的任何建议。
如果我没有理解错的话,这似乎是lag
的工作:
library(dplyr)
data %>% mutate(index2 = if_else(!is.na(index), index, lag(index) * 1.1))
# date index index2
#1 2019-01-01 1.0 1.00
#2 2019-04-01 1.2 1.20
#3 2019-07-01 1.4 1.40
#4 2019-10-01 1.5 1.50
#5 2020-01-01 1.6 1.60
#6 2020-04-01 1.7 1.70
#7 2020-07-01 NA 1.87
#8 2020-10-01 NA NA
#9 2021-01-01 NA NA
这将重现您的预期输出(即仅替换第一个 NA
);我可能误解了您的问题陈述,但我不明白 *apply
与此有什么关系。
您可以实现这样的sapply
位置
transform(data, index2 = c(index[1], sapply(seq_along(index)[-1], function(i)
if (!is.na(index[i])) index[i] else index[i - 1] * 1.1)))
# date index index2
#1 2019-01-01 1.0 1.00
#2 2019-04-01 1.2 1.20
#3 2019-07-01 1.4 1.40
#4 2019-10-01 1.5 1.50
#5 2020-01-01 1.6 1.60
#6 2020-04-01 1.7 1.70
#7 2020-07-01 NA 1.87
#8 2020-10-01 NA NA
#9 2021-01-01 NA NA
但这不是很漂亮。
在您修正错字后,问题陈述略有变化,我们需要 cumprod
data %>%
mutate(index2 = if_else(
!is.na(index),
index,
index[which.max(index)] * cumprod(c(rep(1.0, sum(!is.na(index))), rep(1.1, sum(is.na(index)))))))
# date index index2
#1 2019-01-01 1.0 1.0000
#2 2019-04-01 1.2 1.2000
#3 2019-07-01 1.4 1.4000
#4 2019-10-01 1.5 1.5000
#5 2020-01-01 1.6 1.6000
#6 2020-04-01 1.7 1.7000
#7 2020-07-01 NA 1.8700
#8 2020-10-01 NA 2.0570
#9 2021-01-01 NA 2.2627