2016-09-16 99 views
2

我想在两个治疗组中对不同个体绘制几个测量值。我想显示两列,一列用于第一治疗,一列用于第二治疗。每一列都会为该组中的每个人绘制一张情节。事情是这样的:R ggplot2 facet_grid-like结果但具有独立列

require(ggplot2) 
t <- seq(from=0, to=10, length.out=100) 
ids <- c(1, 17, 22, 4, 55, 74, 88) 
treatment <- c('A', 'A', 'A', 'B', 'B', 'B', 'B') 
df <- NULL 
for (i in 1:length(ids)) 
    df <- rbind(df, data.frame(time=t, treatment=treatment[i], id=ids[i], value=rnorm(length(t)))) 
ggplot(df, aes(y=value, x=time)) + 
    geom_line() + 
    facet_grid(id ~ treatment, scale='free_y') 

产生

Resulting plot

的ID将几乎肯定不会排队等你拿一个号,中间空的图形​​。无论如何,这些ID并不对应于相同的个人,所以不需要排队。我想让ID在两列中独立。有没有方便的方法在ggplot中做到这一点,而不诉诸任何过分哈希或我坚持看着不同的情节并排?我可以给他们“伪”的ID,这将消除间隙,但消除了行标签的实用性。

回答

2

这仅仅是一个头发哈克,但是你可以用组和id生成一个新的变量,然后facet_wrap而不是使用facet_grid。唯一的哈克的部分是确保你有每个组中相同数量的人(这里,将占位空的)

# Generate a label with the individual and id 
df$label <- 
    paste(df$treatment 
     , df$id 
     , sep = ": ") 

# Count the number of individuals in each treatment 
counts <- 
    by(df$id, df$treatment, function(x){length(unique(x))}) 


# For each group, check how many there are 
# If it is less than the max, add a dummy row as a placeholder 
for(i in names(counts)){ 
    if(counts[i] < max(counts)){ 
    df <- rbind(df,data.frame(time=0, treatment=i, id=NA, value=0, label= paste(i, "holder", 1:(max(counts) - counts[i])))) 
    } 
} 

# Plot the result 
ggplot(df, aes(y=value, x=time)) + 
    geom_line() + 
    # Facet on the contstructed label 
    facet_wrap(~label 
      , scale='free_y' 
      # Make sure that you put them in columns, not rows 
      , dir = "v" 
      # Set the number of columns to be the number of groups 
      , ncol = length(unique(df$treatment))) 

enter image description here

如果你真的想保持标签上一边,你可以建立一个联合标签,说明每个组别的个人。标签的结构有点怪异,但我认为它应该是灵活的。请注意,在包含上面构建的额外行之后,您可能不希望运行此操作。

theIndOrders <- 
    split(df$id,df$treatment) %>% 
    lapply(function(x){ 
    1:(length(unique(x))) %>% 
     setNames(sort(unique(x))) 
    }) %>% 
    unlist 

myLabels <- 
    split(names(theIndOrders), theIndOrders) %>% 
    sapply(paste, collapse = "; ") 


df$group <- 
    theIndOrders[paste(df$treatment,df$id, sep = ".")] 

df$myLab <- 
    myLabels[df$group] 


ggplot(df, aes(y=value, x=time)) + 
    geom_line() + 
    # Facet on the contstructed label 
    facet_grid(myLab ~ treatment) 

enter image description here

+0

如果我可以在两侧贴上标签,那么这将是完美的,所以我可以在更多的图表中填满,但这看起来像我可以近距离接近。谢谢! – Anthony

+0

很高兴工作。看到我最近的编辑看到一个版本,标签贴在一边。随着更多的团体,这可能无法正常工作。但是,如果这就是你正在寻找的,这应该工作。 –

2

这可能是你的 “哈克” 的定义,但:

chart <- function(x) { 
    ggplot(x, aes(y=value, x=time)) + 
    geom_line() + 
    facet_grid(id ~ treatment, scale='free_y') 
} 

dplyr::group_by(df, treatment) %>% 
    do(plt=chart(.)) -> plts 

gridExtra::grid.arrange(grobs = plts$plt, ncol=2) 

或者:

map(unique(df$treatment), function(x) { 
    ggplot(dplyr::filter(df, treatment==x), aes(y=value, x=time)) + 
    geom_line() + 
    facet_grid(id ~ treatment, scale='free_y') 
}) -> plts 

gridExtra::grid.arrange(grobs = plts, ncol=2)) 

输出:

Results of the first code snippet

+0

好了,我没注明“过分”哈克,所以我想有一些回旋的余地。这次真是万分感谢!是否有可能做到这一点,保持剧情高度相同?它浪费了一方面的空间,但实际上会更方便。 – Anthony