apply() не присваивает значения

У меня есть подмножество фрейма данных из 16 столбцов. Все они являются факторами с одинаковыми уровнями и ярлыками. Я пытаюсь использовать одну из функций apply() для одновременного назначения уровней и меток, но моя функция печатает результаты, а не присваивает их фрейму данных. Я мог бы выписать их все по отдельности — их всего 16, — но позже у меня есть большие группы переменных, чтобы сделать коэффициенты, так что это сэкономило бы мне много работы.

Пример данных:

df <- structure(list(col1 = c(0L, 1L, 1L, 0L, 1L, 1L, -1L, 0L, 0L, 
1L), col2 = c(0L, 0L, -1L, 0L, -1L, -1L, 1L, 0L, 0L, 1L), col3 = c(-1L, 
1L, 1L, -1L, 0L, 1L, 0L, 0L, -1L, -1L), col4 = c(0L, 0L, 0L, 
1L, 1L, 0L, 0L, 1L, 1L, 0L), col5 = c(-1L, -1L, 0L, 1L, 0L, 0L, 
1L, -1L, 0L, 1L)), .Names = c("col1", "col2", "col3", "col4", 
"col5"), row.names = c(NA, -10L), class = "data.frame")

С этими данными я пробовал:

levels <- -1:1
labels <- c("Don't know", "Not mentioned", "Mentioned")
lapply(as.list(1:5), function(x){
  df[, x] <<- factor(df[, x], levels = levels, labels = labels)
})

Это печатает каждую переменную, а не назначает ее исходному фрейму данных, а также неправильно делает все ячейки NA. Ясно, что я делаю что-то не так, но я не вижу, что (может быть, мне не хватило кофе).

Мой вопрос: как я могу назначить уровни и метки нескольким переменным одновременно, возможно, с помощью функции xapply().

Я видел эту запись на R Блоггеры поэтому использовали <<- вместо <-, но безрезультатно, и я также безуспешно пробовал assign().

Спасибо.


person Phil    schedule 10.05.2015    source источник
comment
Когда я запускаю ваш код, я получаю кадр данных, содержащий значения «Не знаю», «Не упоминается», «Упоминается». Разве это не то, чего вы пытаетесь достичь? Значения в вашем исходном df перезаписываются 3 строковыми значениями.   -  person Brett DeWoody    schedule 11.05.2015
comment
Изменение глобальной среды внутри функции вызывает проблемы. Вместо этого вы можете сделать df[] <- lapply(df, factor, levels = levels, labels = labels).   -  person David Arenburg    schedule 11.05.2015
comment
Спасибо, что заглянули в это. Воспроизводимый пример, который я предоставил, работает с вашими предложениями, а мои фактические данные - нет. Я собираюсь изучить это и, возможно, изменить данные моего примера или попытаться выяснить, почему мои фактические данные не работают. Я после факторов, в идеале.   -  person Phil    schedule 11.05.2015
comment
Мне удалось применить (посмотрите, что я там сделал) предложение @DavidArenburg к моим исходным данным (см. принятый ответ). Любопытно, почему изменение глобальной среды вызывает проблемы; разве это не то, что вы делаете, когда присваиваете значение вне функции? Спасибо.   -  person Phil    schedule 11.05.2015


Ответы (2)


Как упомянул @DavidArenburg, есть лучшие способы сделать это.

Если вам действительно нужны factors, вы можете поступить так, как рекомендовал @David:

df[] <- lapply(df, factor, levels = levels, labels = labels)

[] сохраняет структуру ввода при назначении значения, возвращаемого из примененных вами функций.


Если вас больше всего беспокоит простое символьное представление этих значений, вы можете попробовать что-то другое, например:

df[] <- labels[match(unlist(indf), levels)]
person Community    schedule 11.05.2015
comment
Спасибо, я смог немного изменить это, чтобы внести изменения в исходный набор данных. Я использовал df[] <- lapply(df[, a:b], factor, levels = levels, labels = labels, где a:b — это значения, присвоенные соответствующим номерам столбцов. - person Phil; 11.05.2015
comment
@ Фил, это действительно должно быть df[a:b] <- lapply(df[a:b], ...), верно? (Я пропустил запятую, потому что вы имеете дело с data.frame, а не с matrix, поэтому запятая не необходима (хотя это тоже не помешает). - person A5C1D2H2I1M1N2O1R2T1; 11.05.2015
comment
На самом деле оба работают, но df[, a:b] <- ... заняло меньше времени (хотя и незначительно для набора данных >~3000 переменных). - person Phil; 11.05.2015

Я думаю, что вы, возможно, слишком усердно пытаетесь использовать подход, основанный на apply(), когда простое подмножество может быть намного проще реализовать:

df[,][df[,] == -1] <- "Don't Know"
df[,][df[,] == 0] <- "Not Mentioned"
df[,][df[,] == 1] <- "Mentioned"

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

person Forrest R. Stevens    schedule 11.05.2015
comment
Это очень элегантное решение, очень достойное голосования! Я отмечу решение apply как принятое, потому что технически это ответ на заданный вопрос, но, вероятно, это лучшее решение моей реальной проблемы, поэтому я, вероятно, воспользуюсь этим методом. Спасибо! - person Phil; 11.05.2015