Как перебрать столбцы в data.frame и использовать функцию - PullRequest
1 голос
/ 17 октября 2019

На этот вопрос, вероятно, уже дан ответ, и в этом случае мне жаль повторять вопрос, но, к сожалению, я не смог найти ответ на свою проблему. В настоящее время я пытаюсь работать над читабельностью своего кода и пытаюсь использовать функции чаще, но я не настолько знаком с ним.

У меня есть data.frame, и некоторые столбцы содержат NA, которые я хочу интерполировать, в данном случае, простым фильтром Калмана.

require(imputeTS)

#some test data
col <- c("Temp","Prec")
df_a <- data.frame(c(10,13,NA,14,17),
                   c(20,NA,30,NA,NA))
names(df_a) <- col

#this is my function I'd like to use
gapfilling <- function(df,col){
  print(sum(is.na(df[,col])))
  df[,col] <- na_kalman(df[,col])
}

#this is my for-loop to loop through the columns
for (i in col) {
  gapfilling(df_a, i)
}

У меня две проблемы:

  1. Мой цикл for работает, но он не перезаписывает data.frame. Почему?
  2. Как мне добиться этого без for-loop? Насколько я знаю, вам следует избегать for-loops, если это возможно, и я уверен, что это возможно в моем случае, я просто не знаю, как.

1 Ответ

1 голос
/ 17 октября 2019
Как мне этого добиться без for-loop? Насколько я знаю, вам следует избегать for-loops, если это возможно, и я уверен, что в моем случае это возможно, я просто не знаю, как.

Вы определенно не должны избегать for loops. Чего следует избегать, так это использовать цикл для выполнения действий, которые можно векторизовать. Циклы в целом просто хороши, однако они (намного) медленнее по сравнению со скомпилированными языками, такими как c ++ , но эквивалентны циклам в таких языках, как python .

  1. Мой цикл for работает, но он не перезаписывает data.frame. Почему?

Это проблема с перезаписью значений внутри функции или тем, что называется scope . По существу, любое назначение ограничено его текущей средой (или областью действия). Возьмем следующий пример:

f <- function(x){
    a <- x
    cat("a is equal to ", a, "\n")
    return(3)
}
x <- 4
f(x)
a is equal to  4 
[1] 3
print(a)

Ошибка печати (a): объект 'a' не найден

Как вы можете видеть, «a» определенно существует,но он перестает существовать после выполнения вызова функции. Оно ограничено environment (или scope) функции. Здесь область действия - это время запуска функции.

Чтобы облегчить это, вы должны перезаписать значение в глобальной среде

for (i in col) {
  df_a[, i] <- gapfilling(df_a, i)
}

Теперь для удобства чтения (не скорости) можно изменить это значение на lapply

df_a[, col] <- lapply(df_a[, col], na_kalman)

Я установил тяжелую точку, чтобы она не была быстрее, чем при использовании петли. lapply перебирает каждый столбец, как в цикле. Скорость может быть достигнута, если, скажем, na_kalman был запрограммирован на использование нескольких столбцов и, возможно, сэкономит время, используя оптимизированный код c или c++.

...