如何在R中绘制各列采用独立缩放尺度的热图?
Hey there! I totally get what you're aiming for—building a heatmap where each column uses its own independent color scale, so values in one column don't skew the color interpretation of another. It's easy to think mainstream R packages don't have this covered, but there are actually straightforward workarounds (and even a built-in option you might have missed!). Let's break this down with your specific matrix.
First, let's define your matrix properly so we can work with it:
# Your original matrix mat <- structure(c(37525.6, 38150.7777777778, 54772.3, 76581.6, 89016.8888888889, 132229.2, 47912.2222222222, 57342.2, 61666.6, 2071694.44444444, 4640000, 3397239.5, 310529.6, 433809.7, 437263.8, 23828.1, 33041.3, 47197.3, 19970.4, 11566.4, 14479.1), .Dim = c(3L, 7L), .Dimnames = list(c("Nor", "Plac", "Vaso"), c("Tnf", "Il6", "IL8", "IP10", "MCP1", "GCSF", "IL10")))
This method gives you full control over scaling and visualization, perfect if you want to customize labels, colors, or layout. We'll convert the matrix to a tidy format, scale values per column, then plot with geom_tile.
library(tidyverse) # Convert matrix to a tidy data frame mat_tidy <- mat %>% as.data.frame() %>% rownames_to_column(var = "Group") %>% pivot_longer(cols = -Group, names_to = "Cytokine", values_to = "Value") # Scale values independently for each cytokine (column) # Here we use z-score standardization (mean = 0, SD = 1) mat_tidy_scaled <- mat_tidy %>% group_by(Cytokine) %>% mutate(Scaled_Value = scale(Value)[,1]) %>% ungroup() # Create the heatmap ggplot(mat_tidy_scaled, aes(x = Cytokine, y = Group, fill = Scaled_Value)) + geom_tile(color = "white", size = 0.5) + # Add white borders between tiles scale_fill_gradient2(low = "#2c7fb8", mid = "white", high = "#d95f02", midpoint = 0) + labs(title = "Heatmap with Independent Column Scaling", x = "Cytokines", y = "Sample Groups", fill = "Z-Score") + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1))
If you prefer min-max scaling (values scaled to 0-1 instead of z-scores), replace the mutate line with:
mutate(Scaled_Value = (Value - min(Value)) / (max(Value) - min(Value)))
You might not have noticed, but pheatmap actually has a built-in parameter for column-wise scaling. If you want z-score standardization per column, just use scale = "column":
library(pheatmap) # Built-in column-wise z-score scaling pheatmap(mat, scale = "column", main = "Heatmap with Column-Wise Z-Score Scaling", color = colorRampPalette(c("#2c7fb8", "white", "#d95f02"))(100), border_color = "white")
If you want min-max scaling per column (instead of z-scores), preprocess the matrix first, then pass it to pheatmap:
# Min-max scale each column independently mat_minmax_scaled <- apply(mat, 2, function(x) (x - min(x)) / (max(x) - min(x))) # Plot the pre-scaled matrix pheatmap(mat_minmax_scaled, main = "Heatmap with Column-Wise Min-Max Scaling", color = colorRampPalette(c("#2c7fb8", "white", "#d95f02"))(100), border_color = "white")
- Z-score scaling is great for showing how each value compares to the average of its column (positive = above average, negative = below average)
- Min-max scaling is better if you want to highlight the full range of values within each column, regardless of their distribution
内容的提问来源于stack exchange,提问作者Ibetthat

