You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ggplot2:基于多虚拟变量比例的性别分面柱状图,如何重构数据?

Hey there! Let's fix this up for you—your goal is totally achievable with a bit of data reshaping and tweaking the ggplot code. Here's a step-by-step solution:

Step 1: Reshape Your Data from Wide to Long

Your current data is in "wide" format (each transport mode is a separate column), but we need it in "long" format to easily plot all 9 transport modes at once. We'll use tidyr::pivot_longer() for this, and clean up the transport mode names while we're at it.

First, load the tidyverse package (it includes dplyr, tidyr, and ggplot2 which we'll need):

library(tidyverse)

Then reshape the data:

# Reshape wide data to long format
dfTrans_long <- dfTrans %>%
  pivot_longer(
    cols = starts_with("trans"),  # Select all columns starting with "trans"
    names_to = "transport_mode",  # Name of the new column for transport modes
    values_to = "used"            # Name of the new column for 0/1 values
  ) %>%
  # Clean up the transport mode names (remove the "trans" prefix)
  mutate(transport_mode = str_remove(transport_mode, "trans"))

Step 2: Calculate Proportions of Users (Value = 1) by Gender & Transport Mode

Instead of relying on ..prop.. in ggplot (which can be tricky with facets), let's pre-calculate the proportion of people who used each transport mode (the mean of the used column works perfectly here, since averaging 0s and 1s gives the proportion of 1s):

trans_proportions <- dfTrans_long %>%
  group_by(gender, transport_mode) %>%
  summarize(
    usage_proportion = mean(used),  # Mean of 0/1 equals the proportion of users
    .groups = "drop"                # Drop grouping after calculation
  )

Step 3: Build the Visualization

Now we can create the exact plot you described: 3 rows of 3 transport modes, each row showing gender-specific usage proportions as bars. We'll use facet_wrap() to arrange the 9 modes into 3 rows, and customize axes to show percentages clearly.

ggplot(trans_proportions, aes(x = gender, y = usage_proportion, fill = gender)) +
  geom_col(width = 0.7, show.legend = FALSE) +  # Bars, no redundant legend
  # Format Y-axis as percentages
  scale_y_continuous(
    labels = scales::percent_format(accuracy = 1),
    limits = c(0, 1),  # Optional: Fix Y-axis to 0-100% for consistency
    expand = c(0, 0)   # Remove extra space at the bottom of bars
  ) +
  # Arrange transport modes into 3 rows (matches your 9-variable layout)
  facet_wrap(~transport_mode, nrow = 3) +
  # Add clear labels and clean theme
  labs(
    x = "Gender",
    y = "Percentage of Users",
    title = "Transport Mode Usage by Gender",
    subtitle = "Proportion of respondents who used each transport mode (value = 1)"
  ) +
  theme_minimal() +
  theme(
    axis.text.x = element_text(size = 10),
    strip.text = element_text(size = 11, face = "bold"),
    plot.title = element_text(size = 14, face = "bold")
  )

Why This Works Better Than Your Original Code

  • Data Reshaping: Converting to long format lets us plot all transport modes in one go, instead of writing repetitive code for each column.
  • Pre-Calculated Proportions: Using mean(used) gives a clear, easy-to-interpret measure of usage, avoiding confusion with ..prop.. which depends on strict grouping rules.
  • Facet Layout: facet_wrap(nrow=3) neatly organizes your 9 transport modes into 3 rows, exactly matching your desired layout.

If you want to tweak colors, adjust bar widths, or modify the theme further, you can easily add scale_fill_*() or extra theme() elements.

内容的提问来源于stack exchange,提问作者Gabby Hubert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:07:10