问题
I've read a related post (Simpler population pyramid in ggplot2), but I have a slightly different setup which results in a messed-up pyramid.
Make the test data frame:
test <- data.frame(cbind(c(replicate(3,"population 1"), replicate(3,"population 2")),c("top","middle","bottom","top","middle","bottom"),c(70,25,5,82,13,3)))
Fix the factor ordering:
levels(test$X3)
[1] "13" "25" "3" "5" "70" "82"
test$X3 <- factor(test$X3, levels=c(70,25,5,82,13,3))
levels(test$X2)
[1] "Bottom" "Middle" "Top"
test$X2 <- factor(test$X2, levels=c("Top","Middle","Bottom"))
Try
library(ggplot2)
ggplot(data = test, aes(x=X3, y=X2)) +
geom_bar(data = subset(test, X1=="population 1") , stat = "identity")+
coord_flip()
But it's wrong, and I can't figure out why. The top/middle/bottom factors are in inverse order:
Ultimately I want to make the following:
EDIT - I fixed the one-sided block by imposing the factor re-order in the opposite direction explicitly (below) but I still do not understand why ggplot won't recognize how to plot the data, so any explanation is welcome.
# THIS PLOTS ONE SIDE OF THE PYRAMID CORRECTLY
testdf <- data.frame(cbind(c(replicate(3,"population 1"), replicate(3,"population 2")),c("Top","Middle","Bottom","Top","Middle","Bottom"),c(70,25,5,82,13,3)))
testdf$X3 <- factor(testdf$X3, levels=c(5,25,70,3,13,82))
testdf$X2 <- factor(testdf$X2, levels=c("Bottom","Middle","Top"))
g <- ggplot(data = testdf, aes(x=X3, y=X2))
g <- g + geom_bar(data = subset(testdf, X1=="population 1") , stat = "identity")
g + coord_flip()
回答1:
This should get you started
test <- data.frame(
X1 = c(replicate(3, "population 1"), replicate(3, "population 2")),
X2 = c("top", "middle", "bottom", "top", "middle", "bottom"),
X3 = c(70, 25, 5, 82, 13, 3)
)
test$X2 <- factor(test$X2, levels = c("bottom", "middle", "top"))
ggplot(data = test,
aes(x = X2, y = ifelse(X1 == "population 1", -X3, X3), fill = X1)) +
geom_bar(stat = "identity") +
coord_flip()
回答2:
This is working for me:
test <-
data.frame(
X1 = c(replicate(3, "population 1"), replicate(3, "population 2")),
X2 = c("top", "middle", "bottom", "top", "middle", "bottom"),
X3 = c(70, 25, 5, 82, 13, 3)
)
test$X3 <- with(test, ifelse(X1 == "population 1", -X3, X3))
library(ggplot2)
ggplot(data = test, aes(x = X2, y = X3, fill = X1)) +
geom_col() +
coord_flip() +
scale_y_continuous(labels = abs)
回答3:
Posting this as an answer since it is a solution, after using the help above and pointers from https://rpubs.com/walkerke/pyramids_ggplot2:
Make the dataframe, testdf
. Keep the response, testdf$percent
, as numeric not factor:
testdf <- data.frame(population = c(replicate(3,"population 1"), replicate(3,"population 2")),
layer = c("Top","Middle","Bottom","Top","Middle","Bottom"),
layernum = as.numeric(c(3,2,1,3,2,1)),
percent = as.numeric(c(70,25,5,82,13,3)))
testdf$percent <- ifelse(testdf$population == "population 1", -testdf$percent, testdf$percent)
Use ggplot2
library(ggplot2)
Make the plot:
g <- ggplot(data = testdf, aes(x=layer, y=percent, fill=population))
g <- g + geom_bar(data = subset(testdf, population=="population 1") , stat = "identity")
g <- g + geom_bar(data = subset(testdf, population=="population 2") , stat = "identity")
g <- g + scale_y_continuous(breaks = seq(-100, 100, 25),
labels = paste0(as.character(c(seq(100, 0, -25), seq(25, 100, 25))), "m"))
g+coord_flip()
来源:https://stackoverflow.com/questions/53194064/population-pyramid-in-ggplot