如何用Matplotlib与Numpy绘制散点图比较三个嵌套字典数据
Alright, let's break down how to solve this problem step by step. You've got three nested dictionaries with gene counts, and the main hurdles are matching the inconsistent sample names and then plotting the comparisons. Here's a clear approach:
First, we need to fix the mismatched sample naming formats. Looking at your data:
data_geo1uses long names likeSample_19-leish_023_v2data_geo2uses short names likeSample_19data_alihas both formats
We can write a simple helper function to extract the core sample name from long strings, so we can match across datasets:
def get_core_sample_name(long_sample_name): # Split the name at the first '-' to get the short core name (e.g., Sample_19) return long_sample_name.split('-')[0]
Next, we'll iterate through each gene and collect count pairs where samples match between datasets. We'll create two sets of pairs: one for data_geo1 vs data_ali, and another for data_geo2 vs data_ali.
import numpy as np import matplotlib.pyplot as plt # Helper function from Step 1 def get_core_sample_name(long_sample_name): return long_sample_name.split('-')[0] # -------------------------- # Collect pairs for geo1 vs ali # -------------------------- geo1_ali_pairs = [] for gene in data_geo1: if gene not in data_ali: continue # Skip genes missing in data_ali geo1_samples = data_geo1[gene] ali_samples = data_ali[gene] # Match full sample names (since data_ali has the long names from geo1) for sample in geo1_samples: if sample in ali_samples: geo1_ali_pairs.append((geo1_samples[sample], ali_samples[sample])) # Convert to numpy arrays for plotting geo1_counts, ali_counts_geo1 = np.array(geo1_ali_pairs).T # -------------------------- # Collect pairs for geo2 vs ali # -------------------------- geo2_ali_pairs = [] for gene in data_geo2: if gene not in data_ali: continue # Skip genes missing in data_ali geo2_samples = data_geo2[gene] ali_samples = data_ali[gene] # Match using core sample names (short names from geo2) for short_sample in geo2_samples: # Find the corresponding sample in data_ali for ali_sample in ali_samples: if get_core_sample_name(ali_sample) == short_sample: geo2_ali_pairs.append((geo2_samples[short_sample], ali_samples[ali_sample])) break # Stop after first match to avoid duplicates # Convert to numpy arrays for plotting geo2_counts, ali_counts_geo2 = np.array(geo2_ali_pairs).T
Now we can use Matplotlib to create scatter plots with reference lines (y=x) to visualize how well the counts align between datasets. We'll make two side-by-side plots for clarity:
# Create a 1x2 figure layout fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 6)) # Plot geo1 vs ali ax1.scatter(geo1_counts, ali_counts_geo1, alpha=0.5, s=25) # Add a dashed reference line where x=y ax1.plot([min(geo1_counts), max(geo1_counts)], [min(geo1_counts), max(geo1_counts)], 'r--', linewidth=2) ax1.set_xlabel('data_geo1 Gene Counts', fontsize=12) ax1.set_ylabel('data_ali Gene Counts', fontsize=12) ax1.set_title('data_geo1 vs data_ali', fontsize=14) ax1.grid(True, alpha=0.3) # Plot geo2 vs ali ax2.scatter(geo2_counts, ali_counts_geo2, alpha=0.5, s=25, color='green') ax2.plot([min(geo2_counts), max(geo2_counts)], [min(geo2_counts), max(geo2_counts)], 'r--', linewidth=2) ax2.set_xlabel('data_geo2 Gene Counts', fontsize=12) ax2.set_ylabel('data_ali Gene Counts', fontsize=12) ax2.set_title('data_geo2 vs data_ali', fontsize=14) ax2.grid(True, alpha=0.3) # Adjust spacing between plots plt.tight_layout() plt.show()
- Log Scaling: Gene counts are often log-distributed, so adding
ax1.set_xscale('log')andax1.set_yscale('log')can make low-count data easier to see. - Filter Zero Counts: Remove pairs where either count is 0 to avoid cluttering the plot:
geo1_ali_pairs = [p for p in geo1_ali_pairs if p[0] > 0 and p[1] > 0] - Density Plots: For large datasets, use
plt.hexbin()instead of scatter plots to show data density more clearly.
内容的提问来源于stack exchange,提问作者ALI HAKIMZADEH

