我有数据帧列表,我必须对每个数据帧执行相同的操作。我目前用for loop
执行此操作,但速度太慢了。我想改用lapply
。我需要执行的操作是检查每个数据集的日期列中有多少值从日期向量中丢失。
数据具有以下结构。
# the dates which are of interest
dates <- seq(as.Date("2020-02-01"), as.Date("2020-02-09"), by = "days")
# the list of data frames
df_1 <- data.frame(seq(as.Date("2020-02-01"), as.Date("2020-02-09"), by = "days"), 1:9)
names(df_1) <- c("date", "value")
df_2 <- data.frame(seq(as.Date("2020-02-01"), as.Date("2020-02-07"), by = "days"), 1:7)
names(df_2) <- c("date", "value")
df_list <- list(df_1, df_2)
正在工作但太慢的循环如下所示。
for (i in 1:length(df_list)) {
# get range of dates in the data frame
df_date_range <- unique(df_list[[i]][["date"]])
# get range of dates that occur from the point of the beginning of the data frame
dates_reduced <- dates[dates >= min(df_date_range)]
# get the share of dates missing
missing <- mean(!(dates_reduced %in% df_date_range))
# remove data frames where the share of missing values are above 1 %
if (missing > 0.1) {
df_list[[i]] <- NULL
}
}
我尝试了以下lapply
方法。
# write function to use in lapply
clean <- function(data, date_range) {
# get range of dates in the data frame
df_date_range <- unique(data$date)
# get range of dates that occur from the point of the beginning of the data frame
dates_reduced <- date_range[date_range >= min(df_date_range)]
# get the share of dates missing
missing <- mean(!(dates_reduced %in% df_date_range))
# remove data frames where the share of missing values are above 1 %
if (missing > 0.1) {
data <- NULL
}
}
# apply the function to the list of data frames
new_df_list <- lapply(df_list, clean, date_range = dates)
但是,这只会生成 NULL 列表。对我做错了什么的任何帮助将不胜感激。
虽然我们不必在 R 中显式指定返回值,但这样做总是更好。你的问题说明了这一点!(R 函数隐式返回最后一个表达式的结果,但这并不总是人们所期望的!
请考虑以下函数:
no_explicit_return_value <- function() {
some_non_NULL_value <- 10000
}
如果我们运行:
test_value <- no_explicit_return_value()
test_value
我们回来了:
[1] 10000
自从最后一个表达式返回 10000 以来......到目前为止一切都很好!
现在,考虑这个函数:
no_explicit_return_value <- function() {
some_non_NULL_value <- 10000
if (1000 < 4) {
x <- NULL
}
}
如果我们运行:
test_value <- no_explicit_return_value()
test_value
我们回来了:
NULL
不是因为 if 子句的计算结果为 TRUE,而是因为 if 子句没有返回值
解决方案:
clean <- function(data, date_range) {
# get range of dates in the data frame
df_date_range <- unique(data$date)
# get range of dates that occur from the point of the beginning of the data frame
dates_reduced <- date_range[date_range >= min(df_date_range)]
# get the share of dates missing
missing <- mean(!(dates_reduced %in% df_date_range))
# remove data frames where the share of missing values are above 1 %
if (missing > 0.1) {
data <- NULL
}
return(data)
}
# apply the function to the list of data frames
new_df_list <- lapply(df_list, clean, date_range = dates)
new_df_list
返回:
[[1]]
date value
1 2020-02-01 1
2 2020-02-02 2
3 2020-02-03 3
4 2020-02-04 4
5 2020-02-05 5
6 2020-02-06 6
7 2020-02-07 7
8 2020-02-08 8
9 2020-02-09 9
[[2]]
NULL