Как я могу удалить наборы данных из списка, основанного на условии, используя lapply? - PullRequest
1 голос
/ 09 февраля 2020

У меня есть список фреймов данных, для которых я должен выполнять одинаковые операции для каждого. В настоящее время я делаю это с 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)

l oop, который работает, но работает слишком медленно, выглядит следующим образом.

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)

Это, однако, только дает список пустых значений Любая помощь в том, что я делаю неправильно, будет принята с благодарностью.

1 Ответ

1 голос
/ 09 февраля 2020

Хотя у нас нет для явного указания возвращаемых значений в 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...