我有一个数据集,其中包含来自17个问题的调查答案(10个问题是5个问题或7个问题是7分制),现在数据格式为我每个问题答案(真或假)提供5或7列,就像是一键编码风格。我想将这些列转换回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).
答案 0 :(得分:2)
使用split.default
和max.col
的基本R方法。使用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
答案 1 :(得分:1)
这是一个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"
/ 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")