2016-09-16 62 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