Почему мой код не работает внутри функции, которую я создал, но работает, когда я запускаю его в глобальной среде? - PullRequest
1 голос
/ 10 июня 2019

Итак, у меня есть фрейм данных «fish8», и я попытался написать функцию, которая исключает все пустые строки для трех столбцов фрейма данных (BIN, коллекторы, страна).Дело в том, что код не запускается внутри функции, а работает вне ее.У меня есть много других подобных функций в скрипте, и они работают, почему эта не работает?

#so it doesn't work when I run it like this
remove_empties=function(fish8){
  fish8<<-fish8[!(fish8$BIN == "" | is.na(fish8$BIN)), ]
  fish8<<-fish8[!(fish8$collectors == "" | is.na(fish8$collectors)), ]
  fish8<<-fish8[!(fish8$country == "" | is.na(fish8$country)), ]
}
remove_empties(fish8)

#but it runs like this
fish8<-fish8[!(fish8$BIN == "" | is.na(fish8$BIN)), ]
fish8<-fish8[!(fish8$collectors == "" | is.na(fish8$collectors)), ]
fish8<-fish8[!(fish8$country == "" | is.na(fish8$country)), ]

1 Ответ

2 голосов
/ 10 июня 2019

Проблема связана с областью применения переменных.В этом случае переменная функции fish8 получает назначение в пределах области действия функции.Оригинал fish8 не трогается.См. https://www.r -bloggers.com / dont-run-afoul-of-scoping-rules-in-r / :

Что происходит с << - это то, чтоначинает проходить по дереву среды от дочернего к родительскому, пока не найдет совпадение или не окажется в глобальной (верхней) среде.Это способ начать обход дерева (например, автоматический поиск), но с ужасными последствиями, потому что вы делаете назначение вне текущей области!Будет изменено только первое найденное совпадение, независимо от того, находится оно в глобальной среде или нет. </p>

Возможны следующие варианты:

  1. Удалите двойное назначение и переназначьте результаты.функции на исходный фрейм данных
remove_empties = function(fish8) {
  fish8 <- fish8[!(fish8$x == '' | is.na(fish8$x)), ]
  fish8 <- fish8[!(fish8$y == '' | is.na(fish8$y)), ]
}

fish8 <- remove_empties(fish8)
Использование другой переменной в функции, что было бы лучше, чем использование одного и того же имени переменной в двух разных средах.
remove_empties2 = function(fish) {
  fish <- fish[!(fish$x == '' | is.na(fish$x)), ]
  fish <- fish[!(fish$y == '' | is.na(fish$y)), ]
}

fish8 <- remove_empties2(fish8)
Изменить имя переменной в функции, но глобально присвоить исходную переменную.Мне не нравится этот маршрут:
remove_empties3 = function(fish) {
  fish8 <<- fish[!(fish$x == '' | is.na(fish$x))
                 & !(fish$y == '' | is.na(fish$y)), ]
}

remove_empties3(fish8)
Мой любимый вариант: переназначить пустые строки как NA и затем использовать na.omit().Я также отказался бы от вызова функции - это не более чем на одну дополнительную строку, чем вызов функции, и должен выполняться только один раз, поскольку не следует вводить пустые строки:
fish8[fish8==''] <- NA_character_
fish8 <- na.omit(fish8)

Данные:

set.seed(1)
x <- sample(c('',NA_character_, letters[1:5]), 20, replace = T)
y <- sample(c('', NA_character_, letters[6:10]), 20, replace = T)

fish8 <- data.frame(x, y)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...