使用Python读取Excel数据绘图遇问题:Y轴无值、折线图空白
解决Excel数据可视化的两个问题:Y轴无数值与折线图空白
我来帮你分析并解决这两个问题,先看看核心原因和修正方案:
问题根源分析
- Y轴未显示数值:你在循环里逐个绘制柱状图,每次只传入单个
x和y值,matplotlib无法识别整体的Y轴数据范围,因此不会自动生成刻度。 - 折线图空白:
plt.plot()需要接收一组连续的x和y数据来绘制连线,而你循环中每次只传单个点,相当于绘制了无数个独立的无连线点,视觉上就是空白。
另外,Excel的日期时间在xlrd中会被读取为浮点数,直接用它做x轴会导致matplotlib解析异常,也会间接影响图表显示。
修正后的代码
下面是优化后的完整代码,解决了上述所有问题:
import xlrd from xlrd import xldate_as_datetime import matplotlib.pylab as plt from matplotlib.dates import DateFormatter # 替换为你的文件路径 file_path = "your_file.xls" wb = xlrd.open_workbook(file_path) sheet = wb.sheet_by_index(0) # 初始化列表存储所有数据 x_dates = [] y_values = [] # 批量读取所有行数据 for row_idx in range(sheet.nrows): # 处理日期列:将Excel日期浮点数转换为Python datetime对象 raw_x = sheet.cell_value(row_idx, 0) if sheet.cell_type(row_idx, 0) == 3: # 判断是否为Excel日期类型 raw_x = xldate_as_datetime(raw_x, wb.datemode) x_dates.append(raw_x) # 读取数值列,确保为数值类型 y_val = sheet.cell_value(row_idx, 1) y_values.append(y_val) # 1. 绘制柱状图(修复Y轴数值显示) plt.figure(figsize=(10, 6)) plt.bar(x_dates, y_values) # 设置x轴日期显示格式 date_format = DateFormatter("%Y %m %d %H%M") plt.gca().xaxis.set_major_formatter(date_format) plt.xticks(rotation=50, horizontalalignment='right', weight='bold', size='large') plt.xlabel('Date', weight='bold', size='large') plt.ylabel('Total Bad Ports', weight='bold', size='large') plt.tight_layout() # 自动调整布局,避免标签截断 plt.show() # 2. 绘制折线图(修复空白问题) plt.figure(figsize=(10, 6)) plt.plot(x_dates, y_values, marker='o', linestyle='-', color='blue') # 复用日期格式设置 plt.gca().xaxis.set_major_formatter(date_format) plt.xticks(rotation=50, horizontalalignment='right', weight='bold', size='large') plt.xlabel('Date', weight='bold', size='large') plt.ylabel('Total Bad Ports', weight='bold', size='large') plt.tight_layout() plt.show()
关键修改点说明
- 批量读取数据:不再循环绘制单个元素,而是先把所有x、y数据存入列表,再一次性传递给绘图函数。这样matplotlib能正确计算Y轴范围,自动生成刻度,折线图也能正常连线。
- Excel日期转换:用
xldate_as_datetime把xlrd读取的日期浮点数转为datetime对象,让matplotlib能正确解析和格式化日期轴。 - 日期格式化:添加
DateFormatter自定义x轴日期显示样式,让标签更易读。 - 布局优化:
plt.tight_layout()自动调整图表元素位置,避免x轴标签被截断。
内容的提问来源于stack exchange,提问作者dimitris1780




