Преобразование кадра данных символов в «более четкий» фрейм данных с двоичными переменными в R

Начиная с кадра данных в R, как показано ниже (df):

year_1 <- c('James','Mike','Jane', NA)
year_2 <- c('Evelyn', 'Jackson', 'James', 'Avery')
year_3 <- c('Harper', 'Avery', NA, NA)
df <- data.frame(year_1, year_2, year_3)

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

names <- c('James','Mike','Jane','Evelyn', 'Jackson', 'Avery', 'Harper')
year_1 <- c('YES','YES','YES', 'NO', 'NO', 'NO', 'NO')
year_2 <- c('YES','NO','NO', 'YES', 'YES', 'YES', 'NO')
year_3 <- c('NO','NO','NO', 'NO', 'NO', 'YES', 'YES')
df_1 <- data.frame(year_1, year_2, year_3)
rownames(df_1) <- names

Я пытался:

  1. преобразовать все элементы df в строковый вектор с уникальными элементами
  2. построить структуру df1, используя имена шага 1)
  3. попробуйте заполнить df1 циклом (здесь я не могу построить правильный цикл, который делает трюк)

Есть идеи?

Спасибо!!

Вы можете сделать что-то вроде as.data.frame.matrix(table(stack(df))).

Ritchie Sacramento 17.12.2020 21:24

"Ошибка в stack.data.frame(df): не выбрано ни одного векторного столбца"

vog 17.12.2020 21:26

Убедитесь, что ваши столбцы являются символами, а не факторами.

Ritchie Sacramento 17.12.2020 21:30
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
128
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

вот вариант с tidyverse, где мы преобразуем данные в «длинный» формат pivot_longer, получаем строки distinct, создаем столбец «ДА» и возвращаемся к «широкому» с помощью pivot_wider

library(dplyr)
library(tidyr)
library(tibble)
df %>%
  pivot_longer(cols = everything(), values_drop_na = TRUE) %>%
  distinct %>%
  mutate(new = 'YES') %>% 
  pivot_wider(names_from = name, values_from = new, values_fill = 'NO') %>%
  column_to_rownames("value")

-выход

#          year_1 year_2 year_3
#James      YES    YES     NO
#Evelyn      NO    YES     NO
#Harper      NO     NO    YES
#Mike       YES     NO     NO
#Jackson     NO    YES     NO
#Avery       NO    YES    YES
#Jane       YES     NO     NO

Супер ответ. Очень быстро и чисто!! Большое спасибо

vog 17.12.2020 21:29

Как насчет этого?

sapply(df, function(x) sapply(na.omit(unique(unlist(df))), `%in%`, x))
#         year_1 year_2 year_3
# James     TRUE   TRUE  FALSE
# Mike      TRUE  FALSE  FALSE
# Jane      TRUE  FALSE  FALSE
# Evelyn   FALSE   TRUE  FALSE
# Jackson  FALSE   TRUE  FALSE
# Avery    FALSE   TRUE   TRUE
# Harper   FALSE  FALSE   TRUE

Базовый вариант R с использованием stack + table

> as.data.frame(ifelse(table(stack(df)) == 1, "YES", "NO"))
        year_1 year_2 year_3
Avery       NO    YES    YES
Evelyn      NO    YES     NO
Harper      NO     NO    YES
Jackson     NO    YES     NO
James      YES    YES     NO
Jane       YES     NO     NO
Mike       YES     NO     NO

+1, но я бы, вероятно, использовал lapply(df, as.character), учитывая их комментарий под их вопросом, и замену [] вместо ifelse. Что-то вроде: x <- table(stack(lapply(df, as.character))) + 1; x[] <- c("NO", "YES")[x]; x.

A5C1D2H2I1M1N2O1R2T1 17.12.2020 21:59

@ A5C1D2H2I1M1N2O1R2T1 Да, это имеет смысл, и мы можем использовать type.convert(df,as.is = TRUE), если это возможно

ThomasIsCoding 17.12.2020 22:02

Чтобы предложить другой вариант, сначала мы можем извлечь уникальные имена из df, используя вложенный цикл for. Мы проверяем, есть ли имя уже в нашем списке, и дополнительно проверяем, ищем ли мы NA.

people<-c()
for (i in 1:length(colnames(df))){
  for (j in 1:length(df[,1])){
    pers<-df[j,i]
    if (!(pers %in% people)){
      if (!is.na(pers)){
        people<-c(people,toString(pers))
      }
    }
  }
}

Отсюда мы можем повторять простую проверку %in% каждый год и объединять ее в полный фрейм данных. Приведенные выше ответы, вероятно, более просты, но я обнаружил, что такой код полезен, если вам нужно внести другие небольшие изменения в данные, когда они проходят через сценарий.

for (i in 1:length(colnames(df))){
  colname<-colnames(df)[i]
  peoplein<-people %in% df[,i]
  if (i == 1){
    df1<-cbind(people,peoplein)
    colnames(df1)[i+1]<-colname
  } else {
    df1<-cbind(df1,peoplein)
    colnames(df1)[i+1]<-colname
  }
}

Полученный df1 показан ниже.

     people    year_1  year_2  year_3 
[1,] "James"   "TRUE"  "TRUE"  "FALSE"
[2,] "Mike"    "TRUE"  "FALSE" "FALSE"
[3,] "Jane"    "TRUE"  "FALSE" "FALSE"
[4,] "Evelyn"  "FALSE" "TRUE"  "FALSE"
[5,] "Jackson" "FALSE" "TRUE"  "FALSE"
[6,] "Avery"   "FALSE" "TRUE"  "TRUE" 
[7,] "Harper"  "FALSE" "FALSE" "TRUE" 

Другие вопросы по теме