#r #loops #for-loop
Вопрос:
У меня есть фрейм данных, в котором есть несколько факторных переменных с одинаковыми уровнями. Перечислил уровни ниже
"Completely Agree (3)" "Do not Agree (1)" "Somewhat Agree (2)"
Существует около 18 переменных, которые имеют одни и те же три уровня. Я хочу использовать цикл for и перезаписать эти уровни следующим образом
Не согласен и Несколько Согласен должно быть 0
Полностью согласен, должно быть 1
Я попытался использовать следующий код
for (i in LoopVec.St){
levels(data[,i]) <- c(1,0,0)
}
Лупвек.St содержит имена столбцов всех 18 переменных с одинаковыми уровнями.
levels(data[,i]) <- c(1,0,0)
сработало, когда я использовал его для одной переменной. Но когда я использую его в цикле for, он выдает ошибку ниже.
Ошибка в
levels<-
(*tmp*
, значение = c(1, 0, 0)) : уровень фактора [3] дублируется
Пожалуйста, помогите мне с этим.
Комментарии:
1. Без сайта с вашими данными трудно дать вам конкретный совет. Но использование решения
across
tidyverse позволит вам изменить все 18 переменных в одной строке без использования цикла. Кстати, это почти наверняка тот случай, когда приведение в порядок ваших данных было бы полезно.2. @Limey — не могли бы вы немного подробнее рассказать об этом?
Ответ №1:
В ответ на запрос ОП в комментариях…
library(tidyverse)
# Test data. 3 questions just to demonstrate the principle.
d <- tibble(
Participant=1:10,
Q1=factor(sample(1:3, 10, TRUE), labels=c("Do not Agree (1)", "Somewhat Agree (2)","Completely Agree (3)")),
Q2=factor(sample(1:3, 10, TRUE), labels=c("Do not Agree (1)", "Somewhat Agree (2)","Completely Agree (3)")),
Q3=factor(sample(1:3, 10, TRUE), labels=c("Do not Agree (1)", "Somewhat Agree (2)","Completely Agree (3)"))
)
Для перекодирования факторов
# Recode untidy data
d %>% mutate(
across(
starts_with("Q"),
function(x) factor(as.numeric(x) == 3, labels=c("Do not completely agree (1amp;2)", "Completely agree (3)"))
)
)
# Tidy the data
dTidy <- d %>%
pivot_longer(
cols=starts_with("Q"),
values_to="Response",
names_to="Question"
)
dTidy
# Recode tidy data
dTidy %>%
mutate(
Response=factor(
as.numeric(Response) == 3,
labels=c("Do not completely agree (1amp;2)", "Completely agree (3)")
)
)
Пока особой разницы нет. Преимущество аккуратных данных становится более очевидным, когда мы пытаемся что-то с ними сделать. В качестве простого примера постройте гистограмму вопросов. Неопрятные данные не особенно поддаются обработке. Вот простое резюме:
# Plot untidy data
doPlots <- function(data) {
print(data %>% ggplot() geom_bar(aes(x=Q1)))
print(data %>% ggplot() geom_bar(aes(x=Q2)))
print(data %>% ggplot() geom_bar(aes(x=Q3)))
}
d %>% doPlots()
Все остальное довольно неловко. С аккуратными данными все просто:
# Plot tidy data
dTidy %>%
ggplot()
geom_bar(aes(x=Response))
facet_grid(rows=vars(Question))
# Or
dTidy %>%
ggplot()
geom_bar(aes(x=Response, fill=Question))
Кроме того, предположим, что поступает другой набор данных с большим количеством вопросов, чем исходный.
# Now add another Question
d <- d %>% mutate(Q4=factor(sample(1:3, 10, TRUE), labels=c("Do not Agree (1)", "Somewhat Agree (2)", "Completely Agree (3)")))
dTidy <- dTidy %>%
bind_rows(
tibble(
Participant=1:10,
Question="Q4",
Response=factor(sample(1:3, 10, TRUE), labels=c("Do not Agree (1)", "Somewhat Agree (2)", "Completely Agree (3)"))
)
)
Функцию doPlot необходимо переписать: она игнорирует Q4.
d %>% doPlot()
Но аккуратный код надежен и не нуждается в изменениях
dTidy %>%
ggplot()
geom_bar(aes(x=Response))
facet_grid(rows=vars(Question))
Использование аккуратных данных, на мой взгляд, означает, что ваш код
- более компактная
- легче понять
- более надежный
- проще в обслуживании
- более гибкий
Ответ №2:
Я думаю, вам следует использовать fct_recode()
:
library(tidyverse)
var <- factor(rep(letters[1:3], each = 5))
fct_recode(var, "new1" = "a", "new2" = "b", "new2" = "c")
#> [1] new1 new1 new1 new1 new1 new2 new2 new2 new2 new2 new2 new2 new2 new2 new2
#> Levels: new1 new2
для получения дополнительной информации, например, проверьте книгу r4ds.
Комментарии:
1. Привет, я уже пробовал это. Опять же, это работает, если я запускаю его индивидуально, но при выполнении с использованием цикла for он выдает следующую ошибку. >Ошибка: >
f
должен быть фактор (или вектор символов).
Ответ №3:
Вы используете коэффициент функции следующим образом:
data[,i] = factor(data[,i],
levels= c("Do not Agree (1)",
"Somewhat Agree (2)",
"Completely Agree (3)"
))
Вы также можете проверить различные функции выравнивания tidyverse
. Например fct_relevel
, функция.
https://forcats.tidyverse.org/reference/fct_relevel.html
Комментарии:
1. Я не пытаюсь здесь соотнести факторы. Скорее, я пытаюсь их перекодировать. Я хочу объединить уровни, которые Несколько Согласны и не согласны, и закодировать их как 0 и Полностью согласиться с 1.