我有一个名为“samples”的数据框,如下所示:
sample gender disease treatment
sample1 F d starved
sample2 F c fed
sample3 M d starved
sample4 M d fed
sample5 M d starved
sample6 M c fed
etc
我需要将其导入脚本,然后重新定位()“性别”,“疾病”和“治疗”列。
现在重要的是,我正在构建一个需要尽可能通用的管道 - “样本”中列的名称可能并不总是相同,除了第一列总是被称为“样本”。
因此,我的目标是我的R脚本导入一个配置文件(YAML),这将导致data.frame看起来像这样,并将被称为“因素”:
gender disease treatment
F control fed
现在,我如何循环遍历这些“因素”以告诉它重新定位“样本”中的相应列 - 请注意我如何确保列的名称在2个数据帧之间匹配。我到目前为止尝试过这个但是它不起作用:
for (i in names(factors)){
samples[[i]] <- relevel(samples[[i]], factors[[i]])
}
我得到的错误信息是:
Error in if (ref < 1 || ref > nlev) stop(gettextf("ref = %d must be in 1L:%d", :
missing value where TRUE/FALSE needed
In addition: Warning messages:
1: In Ops.factor(ref, 1) : ‘<’ not meaningful for factors
2: In Ops.factor(ref, nlev) : ‘>’ not meaningful for factors
请注意,您给出的示例中存在数据不一致:factors
包含"disease"
中不存在的samples
的参考级别:"control"
与"c"
。我认为这是一个拼写错误,并且factors
(以及您原来的YAML文件)确实具有列"c"
的参考级别"disease"
(请参阅帖子末尾的示例数据)。
此外,我假设samples
和factors
中所有列的列类是character
。这不应该是一个关键要求,但我没有对samples
或factors
中的列是factor
s的情况进行测试。
这是一个应该很好地概括的选项。
我们从samples
中选择所有列,除了samples$sample
(根据您的问题描述始终存在),并使用purrr::imap
将列转换为factors
和relevel
,使用factors
中相应列条目的参考级别。其余的是与原始samples$sample
柱的柱结合,以给出最终重新平整的samples.relevel
data.frame
。
samples.relevel <- bind_cols(
samples %>% select(sample),
samples %>%
select(-sample) %>%
imap(~ relevel(factor(.x), factors[[.y]])))
str(samples.relevel)
#'data.frame': 6 obs. of 4 variables:
# $ sample : chr "sample1" "sample2" "sample3" "sample4" ...
# $ gender : Factor w/ 2 levels "F","M": 1 1 2 2 2 2
# $ disease : Factor w/ 2 levels "c","d": 2 1 2 2 2 1
# $ treatment: Factor w/ 2 levels "fed","starved": 2 1 2 1 2 1
samples <- read.table(text =
"sample gender disease treatment
sample1 F d starved
sample2 F c fed
sample3 M d starved
sample4 M d fed
sample5 M d starved
sample6 M c fed", header = T, colClasses = "character")
factors <- read.table(text =
"gender disease treatment
F c fed", header = T, colClasses = "character")