Matplotlib.pyplot散点图设置ylim最小值为0无效问题
Let's break down why your scatter plot is getting distorted and how to fix it:
Problem Overview
You're pulling AFL player Nat Fyfe's Disposals stats and trying to visualize them with a scatter plot, but setting the y-axis lower limit to 0 (via plt.ylim(0,50) or plt.ylim(ymin=0)) causes the chart to look compressed and warped. Here's your original code for reference:
import pandas as pd import matplotlib.pyplot as plt stat_dict={'Disposals' : 0, 'Kicks' : 1, 'Marks' : 2, 'Handballs' : 3, 'Goals' : 4, 'Behinds' : 5, 'Hitouts' : 6, 'Tackles' : 7, 'Rebounds' : 8, 'Inside50s' : 9, 'Clearances': 9, 'Clangers' : 10, 'FreesFor' : 11, 'FreesAgainst' : 12, 'ContestedPosessions' : 13, 'UncontestedPosesseions' : 14, 'ContestedMarks' : 15, 'MarksInside50' : 16, 'OnePercenters' : 17, 'Bounces' : 18, 'GoalAssists' : 19, 'Timeplayed' : 20} team_lower_case='fremantle' player="Fyfe, Nat" stat_required='Disposals' rounds=7 tables = pd.read_html("https://afltables.com/afl/stats/teams/" +str(team_lower_case)+"/2018_gbg.html") for df in tables: df.drop(df.columns[rounds+1:], axis=1, inplace=True) # remove unwanted columns df.columns = df.columns.droplevel(0) # remove extra index level stat_table=tables[stat_dict[stat_required]] player_stat=stat_table[stat_table["Player"]==player] player_stat=player_stat.iloc[:,1:8] plt.scatter(range(1,rounds+1),player_stat) plt.ylim(0,50) # or plt.ylim(ymin=0) plt.show()
Root Cause
The issue comes down to data dimensions. When you run player_stat=player_stat.iloc[:,1:8], you end up with a 2-dimensional pandas DataFrame (even though it only has one row of data). plt.scatter treats each column of this DataFrame as a separate dataset, so it's actually plotting 7 overlapping scatter series on the same graph. When you lock the y-axis to start at 0, all these overlapping points create the "compressed" visual effect.
Solution
We just need to convert the 2D DataFrame into a 1D array/Series so plt.scatter only plots one set of points. Here's the fixed code with key improvements:
import pandas as pd import matplotlib.pyplot as plt stat_dict={'Disposals' : 0, 'Kicks' : 1, 'Marks' : 2, 'Handballs' : 3, 'Goals' : 4, 'Behinds' : 5, 'Hitouts' : 6, 'Tackles' : 7, 'Rebounds' : 8, 'Inside50s' : 9, 'Clearances': 9, 'Clangers' : 10, 'FreesFor' : 11, 'FreesAgainst' : 12, 'ContestedPosessions' : 13, 'UncontestedPosesseions' : 14, 'ContestedMarks' : 15, 'MarksInside50' : 16, 'OnePercenters' : 17, 'Bounces' : 18, 'GoalAssists' : 19, 'Timeplayed' : 20} team_lower_case='fremantle' player="Fyfe, Nat" stat_required='Disposals' rounds=7 tables = pd.read_html("https://afltables.com/afl/stats/teams/" +str(team_lower_case)+"/2018_gbg.html") for df in tables: df.drop(df.columns[rounds+1:], axis=1, inplace=True) # Remove extra columns df.columns = df.columns.droplevel(0) # Clean up redundant header level stat_table=tables[stat_dict[stat_required]] player_stat=stat_table[stat_table["Player"]==player] # Convert 2D DataFrame to 1D array - this is the critical fix! player_stat_values = player_stat.iloc[:,1:8].values.flatten() # Plot the scatter graph with clean 1D data plt.scatter(range(1, rounds+1), player_stat_values) # Set y-axis limit without distortion plt.ylim(0, 50) # Add labels and title to make the chart easier to interpret plt.xlabel('Round Number') plt.ylabel('Disposals') plt.title(f'{player} 2018 AFL Disposals (Rounds 1-{rounds})') plt.show()
Key Changes Explained
- Data Dimension Fix: Using
.values.flatten()converts your single-row DataFrame into a 1D numpy array. This ensuresplt.scatterplots only one series of points, not seven overlapping ones. - Chart Readability: Added axis labels and a descriptive title to make the graph more intuitive.
- Proper Y-Axis Limiting: With only one data series plotted, setting
plt.ylim(0,50)constrains the axis correctly without causing visual compression.
After these tweaks, your scatter plot will display normally with the y-axis starting at 0, no distortion included.
内容的提问来源于stack exchange,提问作者Kamila Ambro

