Как сделать новые столбцы данных из факторных уровней (и устранить ошибку мутирования) - PullRequest
0 голосов
/ 10 февраля 2020

Мои поиски в SO и в других местах приводят к интересным решениям проблем, у которых есть похожие поисковые термины, но не моя проблема. Думал, что нашел решение, но из-за ошибки я был озадачен. Я пытаюсь лучше изучить подходы к переходу, но я ценю любые стратегии решения.

Цель: Создание новых векторных столбцов в кадре данных, в котором каждый новый вектор называется из факторного уровня существующий вектор данных. Кодовое решение должно быть динамическим c, чтобы его можно было применять к факторам с любым количеством уровней.

Тестовые данные

df <- data.frame(x=c(1:5), y=letters[1:5])

Который производит как ожидалось

> str(df)
'data.frame':   5 obs. of  2 variables:
 $ x: int  1 2 3 4 5
 $ y: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
> df
  x y
1 1 a
2 2 b
3 3 c
4 4 d
5 5 e

и когда закончил, должен выглядеть как

> df
  x y  a  b  c  d  e
1 1 a NA NA NA NA NA
2 2 b NA NA NA NA NA
3 3 c NA NA NA NA NA
4 4 d NA NA NA NA NA
5 5 e NA NA NA NA NA

Tidy для l oop подхода

library(tidyverse)

for (i in 1:length(levels(df$y))) {
  df <- mutate(df, levels(df$y)[i] = NA)
}

но это дает мне следующую ошибку:

> for (i in 1:length(levels(df$y))) {
+   df <- mutate(df, levels(df$y)[i] = NA)
Error: unexpected '=' in:
"for (i in 1:length(levels(df$y))) {
  df <- mutate(df, levels(df$y)[i] ="
> }
Error: unexpected '}' in "}"

Устранение неполадок, я удалил l oop и упростил mutate, чтобы посмотреть, работает ли он вообще, что он будет с кавычками или без (обратите внимание, я перезапускаю тестовые данные для запуска fre sh) .

levels(df$y)[1]
> "a"

df <- mutate(df, a = NA)
df <- mutate(df, "a" = NA) # works the same as the previous line
> df
  x y  a
1 1 a NA
2 2 b NA
3 3 c NA
4 4 d NA
5 5 e NA

Подстановка функции уровней обратно, но без l oop возвращает ошибку mutate (обратите внимание, я перезапускаю тестовые данные для запуска fre sh) :

> df <- mutate(df, levels(df$y)[1] = NA)
Error: unexpected '=' in "df <- mutate(df, levels(df$y)[1] ="

Я продолжаю получать ту же ошибку, я пытаюсь использовать .data = df, чтобы указать набор данных или оберните as.character (), paste () или paste0 () вокруг функции уровней - которую я подобрал в Интернете для решения других задач. И при этом R просто не придирчив, если я реструктурирую код с использованием%>% pipe.

Что насчет знака равенства, неожиданного для моей подстановки кода уровней (и потенциальных ошибок новичка)? Любая помощь с благодарностью!

1 Ответ

0 голосов
/ 11 февраля 2020

Публикация решений для других на основе полученных комментариев, и поэтому я могу пометить этот вопрос как решенный. Пожалуйста, отдайте голоса @ arg0naut91 и @Gregor за их решения и справочную помощь.

Данные испытаний

df <- data.frame(x=c(1:5), y=letters[1:5])

Решение 1: base R

@ arg0naut91 предоставил элегантное решение base R:

df[, levels(df$y)] <- NA
df
  x y  a  b  c  d  e
1 1 a NA NA NA NA NA
2 2 b NA NA NA NA NA
3 3 c NA NA NA NA NA
4 4 d NA NA NA NA NA
5 5 e NA NA NA NA NA

Решение 2: использование quo () и: =

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

Первый тест с одним новым столбцом:

df <- data.frame(x=c(1:5), y=letters[1:5]) # refresh test data

varlevel <- levels(df$y)[1] # where level 1=a
df <- mutate(df, !!varlevel := NA)
rm(varlevel) # cleanup
df
  x y  a
1 1 a NA
2 2 b NA
3 3 c NA
4 4 d NA
5 5 e NA

Затем поместите его в поле для l oop, чтобы зафиксировать каждый уровень фактора в виде нового столбца:

df <- data.frame(x=c(1:5), y=letters[1:5]) # refresh test data

for (i in 1:length(levels(df$y))) {
+   varlevel <- levels(df$y)[i]
+   df <- mutate(df, !!varlevel := NA)
+   rm(varlevel) # cleanup
+   }
df
  x y  a  b  c  d  e
1 1 a NA NA NA NA NA
2 2 b NA NA NA NA NA
3 3 c NA NA NA NA NA
4 4 d NA NA NA NA NA
5 5 e NA NA NA NA NA
...