我使用ggplot 2.2.0和R版本3.3.2 w64
根据http://www.cookbook-r.com/Graphs/Facets_(ggplot2)/,我可以指定一个提供构面标签的功能。 我绘制了一项研究的患者数据:
我有一个包含ID和数据的数据框,我有第二个数据框包含一些一般信息(年龄和性别)
patmeta <- data.frame(
"pat_id"=c(66, 103, 219, 64, 62, 111, 232),
"gender"=c("f","f","f", "m","f", "f", "f"),
"age"=c(56, 32, 73, 58,37,33,52))
我为pat_id定义了一个全局标签函数和一个特殊的函数(pat_id_fac与pat_id相同但作为因子,pat_id是数字)
PatIdLabeller <- function(id) {
res <- sprintf("Pat %s (%i y, %s)", id,
subset(patmeta, pat_id == id)$age,
subset(patmeta, pat_id == id)$gender)
return(res)
}
globalLabeller <- labeller(
pat_id_fac = PatIdLabeller,
pat_id = PatIdLabeller,
.default = label_both
)
测试PatIdLabeller函数会给出所需的输出(尽管我认为,使用子集不是最优雅的方法),例如
> PatIdLabeller('103')
[1] "Pat 103 (32 y, f)"
但是在ggplot中使用它,ID是正确的,但是年龄和性别都是相同的(patmeta的最后一行),如图所示。
我的qdat的一个子集是以下
structure(list(pat_id = c(103L, 103L, 103L, 64L, 64L, 64L, 66L,
66L, 66L, 219L, 219L, 219L, 62L, 62L, 62L, 111L, 111L, 111L,
232L, 232L, 232L), pat_id_fac = structure(c(4L, 4L, 4L, 2L, 2L,
2L, 3L, 3L, 3L, 6L, 6L, 6L, 1L, 1L, 1L, 5L, 5L, 5L, 7L, 7L, 7L
), .Label = c("62", "64", "66", "103", "111", "219", "232"),
class = c("ordered", "factor")),
Activity = structure(c(9L, 3L, 9L, 2L, 9L, 9L, 9L,
2L, 2L, 3L, 8L, 4L, 2L, 2L, 2L, 4L, 4L, 7L, 2L, 2L, 9L), .Label = c("",
"Anderes", "Essen", "Hausarbeit", "Hobbies", "Körperpflege",
"Liegen", "Medienkonsum", "Sozialer Kontakt"), class = "factor")),
.Names = c("pat_id", "pat_id_fac", "Activity"), row.names = c(1L, 2L, 3L,
128L, 129L, 130L, 199L, 200L, 201L, 217L, 218L, 219L, 343L, 344L, 345L,
397L, 398L, 399L, 451L, 452L, 453L), class = "data.frame")
g.bar.activities <-
ggplot(data=qdat, aes(x=Activity)) +
geom_bar() +
facet_wrap(~ pat_id_fac, labeller= globalLabeller)
从其他问题和答案中,我知道我可以定义一个角色向量,但我很懒,并希望重新使用我的patmeta更优雅,因为研究参与者的名单将变得很长并且随着时间的推移而发展。 / p>
使用较小的测试数据集
t <- data.frame("pat_id"=c(103, 103, 103, 219, 219, 219),
"Activity" = c("sleep", "sleep", "eat", "eat", "eat", "sleep"))
patmeta <- data.frame("pat_id"=c(103, 219),
"gender"=c("m","f"), "age"=c(32,52))
ggplot(data=t, aes(x=Activity)) + geom_bar() +
facet_wrap(~pat_id, labeller=globalLabeller)
我得到了我想要的东西。我没有看到差异。
答案 0 :(得分:1)
似乎子集化工作不正常,可能是因为==
试图沿着传入的所有id
的长度充当向量。也就是说,它检查pat_id
中的每个patmeta
是否与传入的pat_id
相匹配。排序的差异在某种程度上只留下一个pat_id
匹配。
如果您尝试以下任何一项,则可以看到此操作:
PatIdLabeller(c(103, 66))
给出character(0)
并发出此警告:
在pat_id == id:更长的对象中 长度不是较短物体长度的倍数
因为没有行返回,并且R被强制重复==
ggplot(data=head(qdat), aes(x=Activity)) +
geom_bar() +
facet_wrap(~ pat_id, labeller= globalLabeller)
再次给出了重复年龄/性别的情节,以及此警告
在pat_id == id中:较长的对象长度不是a 多个较短的物体长度
(同上)。
值得注意的是,即使使用较小的数据集,如果您反转新patmeta
的行顺序(使219在103之前),则运行您获得的代码
FUN(X [[i]],...)出错:输入未知
因为贴标机返回空character()
(如上所述)。
我没有很多贴标签的经验(这个答案是探索它们的好机会),但是这个应该可以使用来自left_join
的{{1}},而不是尝试使用dplyr
。
==
并使用give:
myLabeller <- function(x){
lapply(x,function(y){
toLabel <-
data.frame(pat_id = y) %>%
left_join(patmeta)
paste0("Pat ", toLabel$pat_id
, " (", toLabel$age, "y, "
, toLabel$gender, ")")
})
}
另一种选择是跳过贴标机步骤,只生成您想直接使用的标签。在这里,只需将元数据与患者数据合并(使用ggplot(data=qdat, aes(x=Activity)) + geom_bar() +
facet_wrap(~pat_id, labeller=myLabeller) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
中的left_join
),然后使用您想要的格式/样式生成列(此处使用dplyr
来自{{ 1}}和mutate
)。
dplyr
然后,使用该数据进行绘图,并将新列用于刻面。
paste0
给出
请注意,facet现在按字母顺序排序,但您可以根据需要进行调整,方法是将列设置为具有显式排序级别的因子。