Skip to content

Cell Composition Analysis: Bar Plot of Cell Type Proportions Across Samples and Groups

Author: SeekGene
Time: 4 min
Words: 612 words
Updated: 2026-02-27
Reads: 0 times
3' scRNA-seq 5' + Immune Profiling Analysis Guide FFPE scRNA-seq Notebooks Plotting Spatial-seq scATAC + RNA-seq scFAST-seq scMethyl + RNA-seq

Load Data

R
# Load cloud platform project data, including Seurat rds and corresponding meta.data
data <- readRDS("/home/demo-seekgene-com/workspace/data/AY1752565399550/input.rds")
meta <- read.table("/home/demo-seekgene-com/workspace/data/AY1752565399550/meta.tsv", 
                  header = TRUE, 
                  sep = "\t", 
                  row.names = 1)
data <- AddMetaData(data, meta.data=meta)

Calculate Total Cell Counts and Proportions for Each Cell Type Across Samples

R

# 1. Prepare data, data is a Seurat object, CellAnnotation is a column name for annotation results in meta.data
cell_counts <- data@meta.data %>%
  count(CellAnnotation) %>%
  mutate(n_thousands = n / 1000)

# 2. Calculate the percentage of each cell type in different samples. CellAnnotation, Sample, and Group are column names in meta.data. Adjust according to your needs.
cell_percentages <- data@meta.data %>%
  count(CellAnnotation, Sample, Group) %>%
  group_by(CellAnnotation) %>%  # Group by cell type
  mutate(percentage = n / sum(n) * 100) %>%
  ungroup()

# 3. Create sample color mapping
sample_info <- data@meta.data %>%
  distinct(CellAnnotation, Group) %>%
  arrange(Group, Sample)

# Assign different colors for AD and Ctrl samples
ad_samples <- sample_info %>% filter(Group == "AD") %>% pull(Sample)
ctrl_samples <- sample_info %>% filter(Group == "Ctrl") %>% pull(Sample)

# Define sample colors, sample name before the equals sign, color after
sample_colors=c("3329"="#004983","4305"="#0040d1","4313"="#3472ff","4443"="#5b8dff",
                "4481"="#6f9bff","4482"="#96b6ff","4627"="#aac4ff","1224"="#ff2668",
                "1230"="#ff3a76","1238"="#ff4e84","3586"="#ff6292","HCT17HEX"="#ff89ad",
                "HCTZZT"="#ffb0c8","NT1261"="#ffc4d6","NT1271"="#ffebf1")
sample_order <- names(sample_colors)  # Get sample order from color mapping
cell_percentages$Sample <- factor(cell_percentages$Sample, levels = sample_order)

Plot Bar Chart of Total Cell Counts for Each Cell Type using ggplot2

R
# 5. Create the upper part
upper_plot <- ggplot(cell_counts, aes(x = CellAnnotation, y = n_thousands, fill = CellAnnotation)) +
  geom_bar(stat = "identity", width = 0.7) +
  scale_fill_manual(values = my36colors[1:length(unique(cell_counts$CellAnnotation))]) +
  labs(title = "Cell Count by Subclustering Type",
       x = "Cell Type", y = "Cell Count (x1000)") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1),
        legend.position = "none",
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.border = element_rect(fill = NA, color = "black"))

Plot Bar Chart of Cell Type Percentages Across Samples using ggplot2

R
# 5. Create the lower part: Percentage stacked bar chart
lower_plot <- ggplot(cell_percentages, aes(x = CellAnnotation, y = percentage, fill = Sample)) +
  geom_bar(stat = "identity", position = "stack", width = 0.7, color = "black", linewidth = 0.3) +
  scale_fill_manual(values = sample_colors,
                   name = "Donor",
                   labels = function(x) paste0(x, " (", sample_info$CellAnnotation[match(x, sample_info$Sample)], ")")) +
  labs(x = "Cell Type", y = "% From Donor") +
  theme_classic() +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1, size = 10),
    axis.text.y = element_text(size = 10),
    axis.title.x = element_text(size = 12, face = "bold"),
    axis.title.y = element_text(size = 12, face = "bold"),
    legend.position = "right",
    legend.title = element_text(face = "bold"),
    legend.key.size = unit(0.4, "cm"),
    panel.grid.major.y = element_line(color = "grey80", linewidth = 0.2),
    panel.border = element_rect(color = "black", fill = NA, linewidth = 0.5)
  ) +
  scale_y_continuous(labels = function(x) paste0(x, "%"),
                     expand = expansion(mult = c(0, 0.05)))

Combine and Save Plots

R
# 6. Combine charts (remove titles for a more scientific style)
combined_plot <- upper_plot / lower_plot +
  plot_layout(heights = c(1, 1.2))

# 7. Display charts
print(combined_plot)

# 8. Save as high-quality image
ggsave("cell_distribution_plot.png", combined_plot, 
       width = 10, height = 8, dpi = 300, bg = "white")

# 9. Verify data
cat("Verify total percentage of each cell type:\n")
validation <- cell_percentages %>%
  group_by(CellAnnotation) %>%
  summarise(total_percent = sum(percentage), .groups = "drop")
print(validation)

cat("\nSample Information:\n")
print(sample_info)
0 comments·0 replies