Matplotlib散点图无法按恶意标签区分点颜色问题求助
Hey Samolivercz, let's get your scatter plot to properly distinguish malicious vs. non-malicious IPs! The most likely issue is that your color parameter isn't tied to the detections-based label you want to use. Here's a step-by-step breakdown with code examples to fix this:
First: Preprocess Your Data
Matplotlib can't plot raw IP address strings directly, so we'll convert them to integers first. We'll also create a clear is_malicious label from your detections column:
import ipaddress import matplotlib.pyplot as plt import numpy as np import pandas as pd # Example DataFrame (replace with your actual data) df = pd.DataFrame({ 'ip': ['192.168.1.1', '10.0.0.1', '172.16.0.5', '8.8.8.8', '192.168.1.10'], 'detections': [0, 3, 0, 5, 2] }) # Convert IP addresses to integers for plotting df['ip_numeric'] = df['ip'].apply(lambda x: int(ipaddress.IPv4Address(x))) # Create binary malicious label: 1 = detections > 0, 0 = no detections df['is_malicious'] = np.where(df['detections'] > 0, 1, 0)
Method 1: Use Scatter's c Parameter (Single Plot Call)
This method binds your is_malicious label directly to the color parameter, using a colormap to separate the two groups:
plt.figure(figsize=(10, 6)) # Plot with color tied to the malicious label scatter = plt.scatter( x=df['ip_numeric'], y=df['detections'], c=df['is_malicious'], cmap='coolwarm', # Red for malicious, blue for non-malicious alpha=0.7, s=100 # Adjust point size if needed ) # Add a legend for the two groups plt.legend( handles=scatter.legend_elements()[0], labels=['Non-Malicious', 'Malicious'] ) # Format x-axis to show IPs instead of integers (rotate for readability) plt.xticks(df['ip_numeric'], df['ip'], rotation=45) plt.xlabel('IP Address') plt.ylabel('Number of Detections') plt.title('IP Address Malicious Status') plt.tight_layout() # Fixes label clipping plt.show()
Method 2: Plot Groups Separately (More Control)
If you want full control over each group's color/style, plot non-malicious and malicious IPs in separate scatter calls:
plt.figure(figsize=(10, 6)) # Plot non-malicious IPs (detections = 0) plt.scatter( x=df[df['is_malicious'] == 0]['ip_numeric'], y=df[df['is_malicious'] == 0]['detections'], color='navy', label='Non-Malicious', alpha=0.7, s=100 ) # Plot malicious IPs (detections > 0) plt.scatter( x=df[df['is_malicious'] == 1]['ip_numeric'], y=df[df['is_malicious'] == 1]['detections'], color='crimson', label='Malicious', alpha=0.7, s=100 ) # Format the plot plt.xticks(df['ip_numeric'], df['ip'], rotation=45) plt.xlabel('IP Address') plt.ylabel('Number of Detections') plt.title('IP Address Malicious Status') plt.legend() plt.tight_layout() plt.show()
Common Mistakes to Check
- You didn't convert IPs to numbers: Matplotlib can't render string values on axes, so raw IPs will cause unexpected behavior (or no plot at all).
- You used a fixed color instead of binding to labels: If you set
c='red'directly, all points will be the same color. Make surecpoints to youris_maliciouscolumn or a similar categorical label. - Your label isn't properly binary: Double-check that
is_maliciousonly has 0 and 1 values (or clear categorical groups) so the colormap can distinguish them.
内容的提问来源于stack exchange,提问作者Samolivercz

