2013-03-14 4 views
4

Есть ли простой способ наклейки отдельных «блоков» в «сложной» гистограмме, такой как следующее. Я бы хотел, чтобы метки располагались ближе к верхней части каждого блока, но мой последний подход приводит к тому, что они каким-то образом заменяют тексты для США и Мексики, как показано ниже.Маркировка отдельных баров в уложенной гистограмме ggplot

example bar graph

Оглядевшись для решения, я только нашел подходы, при котором значение y текста должно быть предварительно вычисленным извне, которые, помимо дополнительной логики, приносят проблемы управления им порядок, в котором блоки уложены ...
Я также нашел эту stackoverflow question где я получил идею использования geom="text" в stat_bin (см код ниже)
Вот урезана фрагмент кода для иллюстрации моего нынешнего подхода. Я не обязательно пытаюсь исправить этот фрагмент, любая общая идиома для ярлыков, которые будут отображаться в столбчатых диаграммах!
Edit: (с учетом двух ответа на этот вопрос получил до сих пор)
Я хотел бы подчеркнуть, что я бы предпочел решения, которые не подразумевают предварительного вычисления у-положение текста ,

# 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() на графике как следуем, но, конечно, значение у было неправильно (шнуровка текстов по отношению к самой нижней части графика, а не, что к нижней части отдельных блоков) ...

... + 
    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

Вот решение. Здесь есть две вещи. Во-первых, вы должны reorder уровней вашего data.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

Edit: Если вы не хотите, чтобы вычислить у-поз самостоятельно, то вам придется использовать 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

Спасибо, Арун, я стараюсь держаться подальше от всех решений, которые предполагают предварительное вычисление позиции у и подачи его к geom_text, но оказывается, что не может быть возможными. .. Знаете ли вы о других идиомах, которые не требуют предварительных вычислений? – mjv

+0

Просто выполните свое первое решение после этого: 'df.StackData $ Страна <- factor (df.StackData $ Страна, levels = c (" Канада "," США "," Мексика "), заказывается = ИСТИНА)' – Arun

+0

Бинго кто это сделал. Я остался с удалением нежелательной легенды, но это должно быть легко. Спасибо! – mjv

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

Спасибо, Рамнатх, я стараюсь держаться подальше от всех решений, которые предполагают предварительную вычисление позиции y и подачу ее на «geom_text», но, похоже, это может быть невозможно ... Знаете ли вы о других идиомы, которые не требуют предварительных вычислений? – mjv

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 [заказ (страна),])

enter image description here

+0

Спасибо, Алекс, это хороший подход. И да, о том, чтобы поместить различные свойства форматирования внутри и снаружи эстетического объекта ... это, конечно, причина - достаточно хорошо, с точки зрения ggplot - для введения большего количества легенд. – mjv

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) 
Смежные вопросы