#r #dataframe
#r #фрейм данных
Вопрос:
У меня есть набор данных с ответами из опроса из 17 вопросов (10 вопросов — это 5 или 7 вопросов по 7-балльной шкале), и теперь формат данных дает мне 5 или 7 столбцов для каждого ответа на вопрос (True или False), что похоже на одноразовый стиль кодирования. И я хочу преобразовать эти столбцы обратно в 15 отдельных столбцов.
Чтобы быть более конкретным, имеющиеся у меня данные выглядят следующим образом
Q1.1 Q1.2 Q1.3 Q1.4 Q1.5 Q1.6 Q1.7 .... Q17.1 Q17.2 ... Q17.5
row1 T F F F F F F F T F
... ...
row2000 F T F F F F F T F F
желаемый формат, который я хочу иметь, это
Q1 Q2 .... Q17
row1 1 4 2 # with number indicating the value that the column is True
....
row2000 2 3 1 #(e.g., if Q2.4 is T, then for Q2, it is 4).
Ответ №1:
Базовый подход R с использованием split.default
и max.col
. С помощью split.default
мы можем разделить столбцы на основе шаблона в их названии, чтобы каждый вопрос был разделен на список. Предполагая, что каждый вопрос будет иметь только одно TRUE
значение, мы можем использовать max.col
для нахождения TRUE
индекса.
sapply(split.default(df, sub("\..*", "", names(df))), max.col)
# Q1 Q2
#[1,] 1 2
#[2,] 6 5
данные
df <-read.table(text = "Q1.1 Q1.2 Q1.3 Q1.4 Q1.5 Q1.6 Q1.7 Q2.1 Q2.2 Q2.3 Q2.4 Q2.5
T F F F F F F F T F F F
F F F F F T F F F F F T", header = T)
Предполагается, что класс ваших данных «логический». Если «T» / «F» хранятся в символьном формате (как в ответе @Maurits), нам нужно сначала преобразовать их в логический.
Используя данные от @Maurits Evers
df[] <- lapply(df, as.logical)
sapply(split.default(df, sub("\..*", "", names(df))), max.col)
# Q1 Q17
#[1,] 1 2
#[2,] 2 1
Ответ №2:
Вот tidyverse
вариант:
library(tidyverse)
df %>%
rownames_to_column("row") %>%
gather(k, v, -row) %>%
separate(k, c("question", "part"), sep = "\.") %>%
filter(v == "T") %>%
group_by(row) %>%
select(-v) %>%
spread(question, part)
## A tibble: 2 x 3
## Groups: row [2]
# row Q1 Q17
# <chr> <chr> <chr>
#1 row1 1 2
#2 row2000 2 1
Я предполагаю, что ваши исходные данные содержат записи "T"
/ "F"
as character
. Если они на самом деле являются TRUE
/ FALSE
, вам следует изменить filter(v == "T")
на filter(v == TRUE)
.
Пример данных
df <- read.table(text =
"Q1.1 Q1.2 Q1.3 Q1.4 Q1.5 Q1.6 Q1.7 Q17.1 Q17.2 Q17.5
row1 T F F F F F F F T F
row2000 F T F F F F F T F F", colClasses = "character")