在一项实验中,我用两种工具调查了不同任务的工作量。 所以我得到了以下结果:
Task1ToolA Task1ToolB Task2ToolA Task2ToolB
P1 3 NA NA 4
P2 NA 4 5 NA
P3 2 NA NA 3
P1,P2,P3是我的测试人员。我的变量是Task1ToolA,Task1ToolB,Task2ToolA,Task2ToolB。
我认为对于评估和策划,我最好有以下内容:
EffortTask1 ToolOfTask1 EffortTask2 ToolOfTask2
P1 3 A 4 B
P2 4 B 5 A
P3 2 A 3 B
第一个表中的每个条目在第二个表中产生两个条目,一个用于分数,一个用于工具。那么,我该如何转换呢?我是R和ggplot2的完全初学者。 谢谢你的回答。
答案 0 :(得分:4)
就我个人而言,我认为您的数据可能会以长格式"而受益。
首先我们重新创建您的数据框:
d <- read.table(text='Task1ToolA Task1ToolB Task2ToolA Task2ToolB
P1 3 NA NA 4
P2 NA 4 5 NA
P3 2 NA NA 3', header=TRUE)
现在以长格式创建一个新数据框:
d_new <- data.frame(
# person: repeat each of the row names as many times as there
# are columns.
person=rep(row.names(d), ncol(d)),
# task: extract the task number (see ?sub), from the column names,
# and repeat each as many times as there are rows.
task=as.numeric(rep(sub('Task(\\d+).*', '\\1', colnames(d)), each=nrow(d))),
# tool: similarly, extract the tool number from the column names,
# and repeat each as many times as there are rows.
tool=rep(sub('.*Tool(.*)', '\\1', colnames(d)), each=nrow(d)),
# score: reduce the data.frame of scores to a vector.
score=unlist(d)
)
看起来像:
d_new
## person task tool score
## Task1ToolA1 P1 1 A 3
## Task1ToolA2 P2 1 A NA
## Task1ToolA3 P3 1 A 2
## Task1ToolB1 P1 1 B NA
## Task1ToolB2 P2 1 B 4
## Task1ToolB3 P3 1 B NA
## Task2ToolA1 P1 2 A NA
## Task2ToolA2 P2 2 A 5
## Task2ToolA3 P3 2 A NA
## Task2ToolB1 P1 2 B 4
## Task2ToolB2 P2 2 B NA
## Task2ToolB3 P3 2 B 3
或者,您可以删除(现在令人困惑的)行名称,并过滤掉NA
分数的行:
d_new <- na.omit(d_new)
row.names(d_new) <- NULL
d_new
## person task tool score
## 1 P1 1 A 3
## 2 P3 1 A 2
## 3 P2 1 B 4
## 4 P2 2 A 5
## 5 P1 2 B 4
## 6 P3 2 B 3
答案 1 :(得分:2)
您可以这样做(数据称为dat
)
res <- do.call(cbind, lapply(split(as.list(dat), grepl("Task2", colnames(dat))), function(x) {
inds <- is.na(x[[1]])
setNames(data.frame(ifelse(inds, x[[2]], x[[1]]), ifelse(inds, "B", "A")),
c("EffortTask", "ToolOfTask"))
}))
setNames(cbind(rownames(dat), res),
c("person", paste0(sub("[A-Z]+\\.", "", names(res)), rep(1:2, each=2))))
# person EffortTask1 ToolOfTask1 EffortTask2 ToolOfTask2
# 1 P1 3 A 4 B
# 2 P2 4 B 5 A
# 3 P3 2 A 3 B
并且(更简单!),使用tidyr
和dplyr
library(dplyr)
library(tidyr)
library(reshape2)
dat %>% mutate(id=rownames(dat)) %>%
melt %>% separate(variable, c("task", "tool"), "Tool") %>%
.[complete.cases(.),]
# id task tool value
# 1 P1 Task1 A 3
# 3 P3 Task1 A 2
# 5 P2 Task1 B 4
# 8 P2 Task2 A 5
# 10 P1 Task2 B 4
# 12 P3 Task2 B 3
答案 2 :(得分:0)
我们可以使用grep
和max.col
来获取输出。
d1 <- data.frame(
lapply(c('Task1', 'Task2'), function(x) {
x1 <- df1[grep(x, names(df1))]
i1 <- max.col(!is.na(x1))
setNames(data.frame(x1[cbind(1:nrow(x1), i1)], LETTERS[i1]),
paste0(c('Effort', 'ToolOf'), x))
}))
row.names(d1) <- row.names(df1)
d1
# EffortTask1 ToolOfTask1 EffortTask2 ToolOfTask2
#P1 3 A 4 B
#P2 4 B 5 A
#P3 2 A 3 B
上述代码涉及的步骤如下。我们使用lapply
lapply(c('Task1', 'Task2'), function(x) {...
然后,我们将&#39; df1&#39;的列进行子集化。使用grep
。
...
x1 <- df1[grep(x, names(df1))]
...
根据&#39; x1&#39;的非NA值创建列索引(&#39; i1&#39;)与max.col
。这基本上给出了每行的最大值的列索引。 !is.na(x1)
返回TRUE/FALSE
值non-NA/NA
的逻辑矩阵。因此,如果{1}}用于第1列的第1行,则返回2,同样,这是针对每一行完成的。
TRUE
在下一步中,我们可以使用&#39; i1&#39;创建...
i1 <- max.col(!is.na(x1))
...
。指数。我们data.frame
使用行索引(cbind
)来创建行/列索引,这可用于从&#39; x1&#39;中提取元素。创造'努力'&#39;柱。 &#39; ToolOf&#39;列是使用&#39; i1&#39;创建的。作为1:nrow(x1)
的索引。
LETTERS
我们更改了&#39;列表&#39; &#39; data.frames&#39;使用...
setNames(data.frame(x1[cbind(1:nrow(x1), i1)], LETTERS[i1]),
paste0(c('Effort', 'ToolOf'), x))
...
调用将单个data.frame更改为原始数据集的data.frame
。
row.names