Вопрос или проблема
Я пытался использовать цикл for
, чтобы создать новые столбцы в фрейме данных, с которым я работаю, чтобы разработать новые переменные для анализа, и у меня возникает много проблем с этим.
У меня есть несколько переменных, которые относятся к акценту партий на различные политические вопросы, и я хотел создать переменные для каждого вопроса, принимая во внимание долю голосов, полученных партией (чтобы определить приближенную оценку того, сколько голосов связано с акцентом на вопрос i партией x).
Таким образом, новые столбцы будут применять следующую операцию: i_emphasis * pervote.
Код, который я написал, заимствован из другого ответа, который я посмотрел в Stack, так как мои первые попытки прошли довольно плохо, но я все равно не понимаю, что происходит. Вот код на данный момент:
vars <- c(y2016_ESP$per101:y2016_ESP$per706)
y2016_ESP %>%
for (i_var in vars){
i_emphasis <- paste0("supp_i_",i_var)
mod_y2016_ESP <- y2016_ESP %>%
mutate(!!sym(i_emphasis) := i_var*pervote)
}
i_var
— это вектор, содержащий все столбцы “акцента на вопросы”, по которым он должен итерироваться, и, похоже, именно он вызывает проблемы. Я не понимаю, почему, так как c()
должен взять каждый отдельный столбец и включить его в вектор (по крайней мере, я думаю, что он должен это делать).
Примечание: Для текущего кода я просто применяю его к сокращенному фрейму данных, так как хотел протестировать его и сначала описательно изучить этот маленький df, а затем применить его более широко к большему фрейму данных. Я видел, что некоторые другие люди используют функции apply()
или lapply()
для выполнения чего-то подобного, но я больше привык к циклам for
, характерным для языков программирования.
Я думаю, что следующее соответствует тому, что вы хотите сделать.
library(dplyr)
y2016_ESP <- data.frame(
per101 = 1:5,
per501 = rnorm(5),
per706 = runif(5)
)
pervote <- .5
# mutate создает новые столбцы
y2016_ESP |>
dplyr::mutate(
dplyr::across(per101:per706, # аккуратно выбрать все столбцы между `per101` и `per706`
~ .x * pervote, # анонимная функция в стиле dplyr
.names = "supp_i_{.col}") # именование новых столбцов в стиле glue
)
Я думаю, что ваше замешательство связано с смешиванием концепций базового R и tidy-select в dplyr.
vars <- c(y2016_ESP$per101:y2016_ESP$per706)
на самом деле не имеет смысла в базовом R, но этот стиль является одним из способов выбора столбцов с использованием dplyr
и across
.
glue
в комментарии выше относится к пакету glue в R. Он часто работает аналогично строкам f в Python.
Вы обычно хотите выбирать между стилем базового R и стилем dplyr и избегать слишком большого смешивания концепций. (Конечно, это не всегда так.)
Я рекомендую книгу R для науки о данных, если вы собираетесь много работать с data.frames.
Если вы действительно хотите итерироваться по именам переменных, вы можете использовать базовый R вместо dplyr.
for (var in list_var) {
df[[var]] # сделайте свое дело
}
Ответ или решение
Чтобы создать новые столбцы в датафрейме в R с использованием цикла for и функции mutate из библиотеки dplyr, важно правильно структурировать код и учитывать некоторые тонкости, касающиеся выбора столбцов и работы с дублирующимися переменными. В данной ситуации мы хотим создать новые переменные, умножая существующие переменные эмфазы партий на общий процент голосов, который они получили.
Подход к решению задачи
-
Создание векторов переменных: Важно убедиться, что вы правильно выбираете столбцы для итерации. Вместо того чтобы использовать
c(y2016_ESP$per101:y2016_ESP$per706)
, рекомендуется использовать функции dplyr для более гибкого выбора столбцов. -
Использование mutate и for loop: Хотя dplyr имеет собственные функции для обработки данных, такие как mutate и across, возможно, что для большей визуализации вы хотите использовать циклы.
Реализация
Ниже приведен пример кода, который показывает, как правильно использовать цикл for вместе с mutate. Для начала создадим пример датафрейма и переменной для процента голосов:
library(dplyr)
# Пример датафрейма
y2016_ESP <- data.frame(
per101 = 1:5,
per501 = rnorm(5),
per706 = runif(5)
)
# Процент голосов
pervote <- 0.5
# Список переменных к итерации
vars <- colnames(y2016_ESP) # получаем названия всех столбцов
# Итерация по переменным
for (i_var in vars){
# Создаем новое имя для переменной
new_col_name <- paste0("supp_i_", i_var)
# Обновляем датафрейм, добавляя новый столбец
y2016_ESP <- y2016_ESP %>%
mutate(!!sym(new_col_name) := .data[[i_var]] * pervote)
}
Пояснение к коду
-
Создание датафрейма: Мы создали датафрейм
y2016_ESP
с некоторыми тестовыми данными. -
Процент голосов: У нас есть переменная
pervote
, которая хранит процент голосов, с помощью которого мы будем умножать значения эмфазы. -
Цикл for: Мы проходим по именам столбцов в
vars
, создаём новое имя для каждого столбца с помощью функцииpaste0
, и с помощью функцииmutate
добавляем новый столбец в датафрейм. -
Использование !!sym: Мы используем
!!sym()
для преобразования строкового имени переменной в символ, который dplyr может распознать и использовать.
Заключение
Этот способ позволяет делать более сложные операции над датафреймом с использованием стандартных средств R. Обратите внимание на использование mutate
для добавления новых переменных и использование двойного восклицательного знака (!!), который сообщает dplyr, что вы собираетесь передать символ в функцию. Для более эффективной работы с большим объемом данных вы можете использовать функции dplyr, такие как across
, однако использование циклов может сделать ваш код более читаемым для тех, кто не знаком с функциональным программированием.
Рекомендации
- Ознакомьтесь с литературой по R, например, "R for Data Science" by Hadley Wickham. Это поможет вам улучшить свои навыки в работе с данными.
- Если вам необходимы более сложные операции, рассмотрите возможность использования функций
lapply
илиsapply
, так как они могут упростить операции по сравнению с ручными циклами.