admin管理员组

文章数量:1279055

Here is my graph so far:

counts <- table(all_study$study, all_study$time_of_day_num)
barplot(counts, main="Distribution of Enrollment Time by Study for 24-25",
        col=c("blue","red","green","yellow","orange"),
        ylab= "Count",  names.arg=c("Night", "Evening", "Day"))
legend(0.2,70, legend=c("MATIC","TCD-2","TROOP","Lublin","Microbiome"), 
       fill=c("orange","yellow","green","red","blue"), cex=0.75)

And here is what the graph looks like:

I am trying to figure out how to place the count of each study under each type of day. For example, it looks like there is about 25 Microbiomes under Night and 2 TROOP under Night. So I want the number 25 placed in the center of the blue bar for night and 2 squeezed into the green bar for night.

I have tried text() and things like stat='count' and more.

Here is my graph so far:

counts <- table(all_study$study, all_study$time_of_day_num)
barplot(counts, main="Distribution of Enrollment Time by Study for 24-25",
        col=c("blue","red","green","yellow","orange"),
        ylab= "Count",  names.arg=c("Night", "Evening", "Day"))
legend(0.2,70, legend=c("MATIC","TCD-2","TROOP","Lublin","Microbiome"), 
       fill=c("orange","yellow","green","red","blue"), cex=0.75)

And here is what the graph looks like:

I am trying to figure out how to place the count of each study under each type of day. For example, it looks like there is about 25 Microbiomes under Night and 2 TROOP under Night. So I want the number 25 placed in the center of the blue bar for night and 2 squeezed into the green bar for night.

I have tried text() and things like stat='count' and more.

Share Improve this question edited Feb 25 at 8:23 Tim G 4,2521 gold badge2 silver badges15 bronze badges asked Feb 25 at 7:55 Cami VinzCami Vinz 331 silver badge4 bronze badges 3
  • "things like stat='count'" That's ggplot2 code. Indeed, I recommend doing this with ggplot2. – Roland Commented Feb 25 at 7:58
  • It would be nice to have some data to play with. My initial guess is to save the barplot command to an object, say bp which saves the midpoints of each bar for further use. I'm sure this has been asked and answered before. For example: here, here and here – Edward Commented Feb 25 at 8:00
  • The help page of barplot has an example using the VADeaths dataset. – Edward Commented Feb 25 at 8:07
Add a comment  | 

2 Answers 2

Reset to default 2

You could write an ymids() function, that calculates a cumulative sum, where the new element is always halved, i.e. x1/2, x1 + x2/2, x1 + x2 + x3/2, ... .

> ymids <- \(x) {
+   r <- numeric(length(x))
+   for (i in seq_len(length(x))) {
+     if (i == 1) {
+       r[i] <- x[i]/2
+     } else {
+       r[i] <- sum(x[seq_len(i - 1)]) + x[i]/2
+     }
+   }
+   r
+ }
> b <- barplot(counts, col=hcl.colors(4, alpha=.5))
> text(b, t(apply(counts, 2, ymids)), labels=t(counts))

If you really want these grey labels you can invent sth with rect, but IMO it would just clutter the plot and adds no useful information.


Data:

> dput(counts)
structure(c(5L, 18L, 11L, 5L, 6L, 3L, 6L, 12L, 14L, 6L, 11L, 
6L), dim = 4:3)

We can calclate the middle heights ym of each stacked bar with cumsum().

This approach adds 'white' labels. If you do not like it, just remove rect(), use a different colour palette or adjust the opacity in hcl.colors() via it's alpha-argument.

 nr = nrow(counts2)
 b = barplot(counts2, col=hcl.colors(n=nr), ylab='Count', 
             legend.text=row.names(counts2),
             main='Distribution of Enrollment Time by Study for 24-25', 
             args.legend=list(x=4L, y=-7L, horiz=TRUE))
 ym = apply(counts2, 2L, cumsum) - counts2 / 2L
 rect(b-.07, t(ym)-1L, b+.07, t(ym)+1L, col='white')
 text(rep(b, each=nr), ym, labels=t(counts2))

Please adapt the xy-coords in args.legend of barplot() and rect() according to your needs.

Short-cut version

where the qualitative colour palette 'Dark 2' is used.

b = barplot(counts2, col=hcl.colors(n=nrow(counts2)))
ym = apply(counts2, 2L, cumsum) - counts2 / 2L
rect(b-.07, t(ym)-1L, b+.07, t(ym)+1L, col='white')
text(rep(b, each=nrow(counts2)), ym, labels=t(counts2))

Running both nrow(counts2) and t(ym) twice should be tolierable overhead here.


Data

User jay.sf's counts modified to match OP's data in dimension.

counts2 = structure(c(5, 18, 11, 5, 6, 6, 3, 6, 12, 10, 14, 6, 11, 6, 8), dim = c(5L, 3L), dimnames = list(c("MATIC", "TCD-2", "TROOP", "Lublin", "Microbiome"), c("Night", "Evening", "Day")))
> counts2
#>            Night Evening Day
#> MATIC          5       6  14
#> TCD-2         18       3   6
#> TROOP         11       6  11
#> Lublin         5      12   6
#> Microbiome     6      10   8

本文标签: rHow do I add counts to a stacked bar graphStack Overflow