Как привести в порядок этот грязный набор данных в R
Я довольно новичок в использовании tidyr
, dplyr
и т.д., и у меня есть некоторые данные, которые я не могу понять, как привести в порядок R
,
Переменные смешиваются в строках и столбцах, и электронная таблица выглядит так, как будто она разделена, поэтому в верхних и нижних строках есть разные виды информации.
Упрощенная версия этого ниже.
Вы можете представить, что это экзамен с 4 вопросами:
- В верхних строках приведена информация о каждом вопросе.
- Нижние ряды показывают, являются ли различные студенты (данные их
IDNum
) получил правильные вопросы (1
) или неправильно (0
).
Вот необработанные данные:
Question Q1 Q2 Q3 Q4
Topic English English Math Math
Subtopic Grammar Vocabulary Algebra Geometry
Difficulty 2 4 3 4
IDNum
512 1 1 1 0
102 0 1 0 1
321 1 1 1 1
246 1 1 0 1
248 1 0 1 0
136 1 1 1 1
290 0 1 1 1
753 1 0 0 0
752 1 0 1 1
Я хотел бы привести в порядок этот набор данных. Это будет выглядеть примерно так:
IDNum Question Topic Subtopic Difficulty Correct
512 Q1 English Grammar 2 1
512 Q2 English Vocabulary 4 1
512 Q3 Math Algebra 3 1
512 Q4 Math Geometry 4 0
102 Q1 English Grammar 2 0
102 Q2 English Vocabulary 4 1
102 Q3 Math Algebra 3 0
102 Q4 Math Geometry 4 1
321 Q1 English Grammar 2 1
321 Q2 English Vocabulary 4 1
321 Q3 Math Algebra 3 1
321 Q4 Math Geometry 4 1
и так далее.
Спасибо!
1 ответ
Не совсем ясно, в каком формате у вас есть данные, но, надеюсь, поможет следующее:
данные
df <- read.table(text="
Question Q1 Q2 Q3 Q4
Topic English English Math Math
Subtopic Grammar Vocabulary Algebra Geometry
Difficulty 2 4 3 4
IDNum '' '' '' ''
512 1 1 1 0
102 0 1 0 1
321 1 1 1 1
246 1 1 0 1
248 1 0 1 0
136 1 1 1 1
290 0 1 1 1
753 1 0 0 0
752 1 0 1 1",h=F,strin=F)
решение
library(tidyverse)
df %>%
# collapse the first rows into column names to prepare for gather/separate combo
setNames(apply(.[1:4,],2,paste,collapse="|")) %>%
rename_at(1,~"IDNum") %>%
# remove useless rows
slice(-(1:5)) %>%
# change IDNum to factor, only useful if the order of IDNum is important (probably it's not)
mutate_at("IDNum",~factor(.x,levels=unique(.x))) %>%
# wide to long
gather(key,correct,-1) %>%
# build your columns (convert to TRUE so Difficulty will be numeric)
separate(key,df[1:4,1],convert = TRUE) %>%
# convert correct to numeric
mutate_at("correct",as.numeric) %>%
# sort
arrange(IDNum)
# # A tibble: 36 x 6
# IDNum Question Topic Subtopic Difficulty correct
# <fctr> <chr> <chr> <chr> <int> <dbl>
# 1 512 Q1 English Grammar 2 1
# 2 512 Q2 English Vocabulary 4 1
# 3 512 Q3 Math Algebra 3 1
# 4 512 Q4 Math Geometry 4 0
# 5 102 Q1 English Grammar 2 0
# 6 102 Q2 English Vocabulary 4 1
# 7 102 Q3 Math Algebra 3 0
# 8 102 Q4 Math Geometry 4 1
# 9 321 Q1 English Grammar 2 1
# 10 321 Q2 English Vocabulary 4 1
# # ... with 26 more rows
Другой способ, с несколькими дополнительными шагами, но, возможно, более интуитивным, состоит в том, чтобы отделить от начала заголовок и ядро таблицы.
Мы создаем поиск из заголовка (который мы транспонируем), и мы будем использовать его для собранных данных позже:
header_lkp <-
as_tibble(t(df[1:4,])) %>%
setNames(.[1,]) %>%
slice(-1)
df_core <-
df %>%
setNames(.[1,]) %>%
slice(-(1:5)) %>%
rename_at(1,~"IDNum") %>%
mutate_at("IDNum",~factor(.x,levels=unique(.x)))
df_core %>%
gather(Question,correct,-IDNum) %>%
mutate_at("correct",as.numeric) %>%
left_join(header_lkp,by="Question") %>%
arrange(IDNum)
(тот же вывод)