2013-03-14 79 views
4

是否有一種簡單的方法在如下所示的「堆疊」條形圖中標記個體「塊」。我希望將標籤放置在每個塊的頂部附近,但是我最新的方法會以某種方式導致美國和墨西哥的文本交換如下。在堆疊的ggplot條形圖中標記單個條

example bar graph

四處尋找一個解決方案,我只找到方法,其中文本的y值必須在外部預先計算,其中,除了額外的邏輯,使控制的問題順序塊堆疊...
我也發現了這個stackoverflow question那裏我得到了一個stat_bin使用geom="text"(見下面的代碼)
下面是我目前的做法進行說明的下調代碼片段的想法。 我不一定要修復這個片段,任何通用的成語標籤堆棧條形圖區域都可以!
編輯:(鑑於這兩個回答這個問題得到了到目前爲止)
我想強調的是,我寧願解決方案,這並不意味着預先計算文本的y位置。

# sample data source 
df.StackData <- data.frame(
    QType = c("A4-1", "A4-1", "A4-1", "B3", "B3", "B3"), 
    Country = c("Canada", "USA", "Mexico", "Canada", "USA", "Mexico"), 
    NbOfCases = c(1000, 1320, 380, 400, 1000, 812), 
    AvgRate = c(17.2, 11.4, 44.21, 17.3, 15.3, 39.7), 
    Comment = c("Can", "US", "Mex", "Can", "US", "Mex") 
) 

和ggplot調用。 它產生上面顯示的圖形,帶有標籤的奇數交換(還有一個額外的圖例,'雖然這個傳奇問題很容易處理;我只是在準備這個問題時注意到了這一點)。

ggplot(data=df.StackData, 
     aes(x=QType, y=NbOfCases, fill=Country))+ 
    geom_bar(stat="identity", width=1) + 
    stat_bin(geom="text", aes(label=paste("R coef =", 
             formatC(AvgRate, format="f", digits=3), 
             "(", Comment, ")"), 
          vjust=1.5, size=3 
         ) 
) 

我的初始嘗試加入geom_text()到圖形如下,但當然的y值是錯誤的(相對於圖的最底部,而不是對各個塊的底部繫帶文本) ...

... + 
    geom_text(mapping=aes(x=QType, y=NbOfCases, 
         label=paste("R coef =", 
            formatC(AvgRate, format="f", digits=3), 
            "(", Comment, ")"), 
         vjust=1.5), 
      size=3) 

回答

2

這是一個解決方案。這裏有兩件事。首先,您應將reorderdata.frame的級別設置爲與您的數據df.StackData中的級別相同。其次,創建另一個data.frame,通過計算數據的累計和來計算y-position

# reorder levels of factor to the same order as found in data 
df.StackData$Country <- factor(df.StackData$Country, 
      levels=c("Canada", "USA", "Mexico"), ordered=TRUE) 
p <- ggplot(data=df.StackData, aes(x=QType, fill=Country)) 
p <- p + geom_bar(aes(weights=NbOfCases)) 

# compute corresponding y-axis positions by cumulative sum 
require(plyr) 
df <- ddply(df.StackData, .(QType), function(x) { 
    x$NbOfCases <- cumsum(x$NbOfCases) 
    x 
}) 

# then use geom_text with data = df (the newly created data) 
p + geom_text(data = df, aes(x=QType, y=NbOfCases, 
     label=paste("R coef =", 
     formatC(AvgRate, format="f", digits=3), 
     "(", Comment, ")"), vjust=1.5), size=3) 

enter image description here

編輯:如果你不想計算的y POS自己,那麼你將不得不使用stat_bin。只需重新排序Country列的水平和它的工作原理:

# data 
df.StackData <- data.frame(
    QType = c("A4-1", "A4-1", "A4-1", "B3", "B3", "B3"), 
    Country = c("Canada", "USA", "Mexico", "Canada", "USA", "Mexico"), 
    NbOfCases = c(1000, 1320, 380, 400, 1000, 812), 
    AvgRate = c(17.2, 11.4, 44.21, 17.3, 15.3, 39.7), 
    Comment = c("Can", "US", "Mex", "Can", "US", "Mex") 
) 

# just add this: reorder the level 
df.StackData$Country <- factor(df.StackData$Country, 
      levels=c("Canada", "USA", "Mexico"), ordered=TRUE) 

# your code again using stat_bin (just changed the width to 0.75) 
ggplot(data=df.StackData, 
     aes(x=QType, y=NbOfCases, fill=Country))+ 
    geom_bar(stat="identity", width=.75) + 
    stat_bin(geom="text", size=4, aes(label=paste("R coef =", 
             formatC(AvgRate, format="f", digits=3), 
             "(", Comment, ")"), 
          vjust=1.5)) 

enter image description here

+0

謝謝你,阿倫,我試圖從暗示預先計算y位置和其送入geom_text的所有解決方案望而卻步,但現在看來,可能是不可能的。 ..你知道其他不需要預先計算的成語嗎? – mjv 2013-03-14 21:16:14

+0

只需嘗試一下你的第一個解決方案:'df.StackData $ Country < - factor(df.StackData $ Country,levels = c(「Canada」,「USA」,「Mexico」),ordered = TRUE)' – Arun 2013-03-14 21:21:44

+0

Bingo它做到了。我留下去除了不想要的傳說,但這應該很容易。謝謝! – mjv 2013-03-14 21:30:02

2

這裏是一個解決方案

df2 = ddply(df.StackData, .(QType), transform, 
pos = cumsum(NbOfCases) - 0.5 * NbOfCases) 

ggplot(data = df2, aes(x = QType, y = NbOfCases, fill = Country)) + 
    geom_bar(stat = "identity") + 
    geom_text(aes(y = pos, label = paste("R coef =", 
    formatC(AvgRate, format="f", digits=3), "(", Comment, ")")) 
) 

Imgur

+0

謝謝Ramnath,我試圖遠離所有預先計算y位置並將它提供給'geom_text'的解決方案,但似乎可能不可能......你知道其他不需要預先計算的成語? – mjv 2013-03-14 21:11:53

1

這裏有一個選擇 - 因爲你的因素會按字母順序排序默認情況下,我建議重新排序您的數據框以與此匹配,而不是重新排序因子ch數據幀的順序。在我看來,這將允許一個更一般的解決方案。你得到一個你不想要的傳說的唯一原因是你的尺寸在aes之內 - 我在下面修正了這個。

使用您的數據:

df.StackData <- with(df.StackData, df.StackData[order(Country),]) 

,然後你可以使用你原來的解決方案與stat_bin。我有點更復雜的數據集的測試,它只是爲了檢查是否正常工作:

df.StackData <- data.frame(
    QType = rep(c("A4-1","B3"), each = 6), 
    Country = rep(c("Canada", "USA", "Mexico", "UK", "Sweden", "Australia"), times = 2), 
    NbOfCases = c(1000, 1320, 380, 400, 1000, 812, 542, 531, 674, 328, 795, 721), 
    AvgRate = c(17.2, 11.4, 44.21, 17.3, 15.3, 39.7, 21.1, 25.3, 24.1, 31.3, 38.4, 36.1), 
    Comment = rep(c("Can", "US", "Mex", "UK", "Aus", "Swe"), times = 2) 
) 

不排序:

ggplot(data=df.StackData, 
     aes(x=QType, y=NbOfCases, fill=Country))+ 
    geom_bar(stat="identity", width=1) + 
    stat_bin(geom="text", aes(label=paste("R coef =", formatC(AvgRate, format="f", digits=3), 
"(", Comment, ")"), vjust = 1),size=3) 
geom_text(aes(label = Comment), stat="identity") 

enter image description here

排序後:

df.StackData < - 與(df.StackData,df.StackData [order(Country),])

enter image description here

+0

謝謝Alex,這也是一個很好的方法。關於將各種格式屬性放在內部與外部的審美對象之間......這當然是原因 - 從ggplot的觀點來看 - 當然這是引入更多傳說的原因。 – mjv 2013-03-15 01:52:51

1

爲了刪除額外的圖例,您可以使用show_guide=FALSE。在您的例子:

ggplot(data=df.StackData, 
     aes(x=QType, y=NbOfCases, fill=Country))+ 
    geom_bar(stat="identity", width=.75) + 
    stat_bin(geom="text", size=4, aes(label=paste("R coef =", 
             formatC(AvgRate, format="f", digits=3), 
             "(", Comment, ")"), 
          vjust=1.5), show_guide=FALSE)