Python绘制柱状图时设定取值范围为变量 解决计数高度异常问题
错误原因
- 多余的追加操作:你主动把150~190的步长数值追加到了原数据集末尾,相当于给每个数值新增了1条无效样本,这是数值类柱高全为1的核心原因。
- 数据类型不匹配:原数据PT1列中的数值为字符串格式,你定义的分类列表中数值为整数格式,分类匹配时二者无法对应,原数据中的数值会被识别为无效分类,不计入统计结果。
- 分类命名不一致:原数据中未完成的标识为
NOT_FINISHED,你定义的分类为NOT_COMPLETED,二者不统一会导致该类数据无法被统计。 - 未处理异常值:原数据中的空值、小于150的数值没有做映射,不会被计入有效分类。
修正后代码
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 加载原始数据,下方为你给出的示例测试数据 df = pd.DataFrame({'ID': {0: 'GF342', 1: 'IF874', 2: 'FH386', 3: 'KJ190', 4: 'TY748', 5: 'YT947', 6: 'DF063', 7: 'ET512', 8: 'GC714', 9: 'SD978', 10: 'EF472', 11: 'PL489', 12: 'AZ315', 13: 'OL821', 14: 'HN765', 15: 'ED589'}, 'Location': {0: 'Q1', 1: 'Q3', 2: 'Q1', 3: 'Q3', 4: 'Q3', 5: 'Q4', 6: 'Q3', 7: 'Q1', 8: 'Q2', 9: 'Q3', 10: 'Q1', 11: 'Q2', 12: 'Q1', 13: 'Q1', 14: 'Q3', 15: 'Q1'}, 'NEW': {0: 'YES', 1: 'NO', 2: 'NO', 3: 'YES', 4: 'YES', 5: 'NO', 6: 'NO', 7: 'YES', 8: 'NO', 9: 'NO', 10: 'NO', 11: 'YES', 12: 'NO', 13: 'YES', 14: 'YES', 15: 'YES'}, 'YEAR': {0: 2021, 1: 2018, 2: 2019, 3: 2021, 4: 2021, 5: 2019, 6: 2019, 7: 2021, 8: 2018, 9: 2019, 10: 2018, 11: 2021, 12: 2018, 13: 2021, 14: 2021, 15: 2021}, 'PT1': {0: '', 1: 'NOT_TESTED', 2: '', 3: 'NOT_FINISHED', 4: '165', 5: '', 6: '180', 7: '145', 8: '155', 9: '', 10: '', 11: '', 12: 'TOO_LOW', 13: '150', 14: '155', 15: ''}, 'PT2': {0: '', 1: '', 2: '', 3: '', 4: '', 5: 'TOO_LOW', 6: '', 7: '', 8: '160', 9: 'TOO_LOW', 10: '', 11: '', 12: '', 13: '', 14: '', 15: ''}, 'PT3': {0: '', 1: 'TOO_LOW', 2: '', 3: 'TOO_LOW', 4: '', 5: '', 6: '', 7: '', 8: '', 9: '', 10: '', 11: 'NOT_FINISHED', 12: '', 13: '185', 14: '', 15: '165'}, 'PT4': {0: '', 1: '', 2: '', 3: '', 4: '', 5: 165.0, 6: '', 7: '', 8: '', 9: '', 10: '', 11: '', 12: 180.0, 13: '', 14: '', 15: ''}}) # 定义分类规则 num_range = list(range(150, 191, 5)) OUTCOMES = ['NOT_TESTED', 'NOT_COMPLETED', 'TOO_LOW'] + num_range # 处理PT1列数据 def map_pt1(value): # 统一未完成标识 if value == 'NOT_FINISHED': return 'NOT_COMPLETED' # 空值返回None后续过滤 if value == '': return None # 尝试转换为数值 try: num_val = int(float(value)) # 符合范围返回数值,小于150归为TOO_LOW return num_val if num_val in num_range else 'TOO_LOW' except: # 已有分类标识直接返回 return value if value in OUTCOMES else None df['outcomes_col'] = df['PT1'].apply(map_pt1) # 过滤空值,设置分类顺序 df = df.dropna(subset=['outcomes_col']) df['outcomes_col'] = df['outcomes_col'].astype('category').cat.set_categories(OUTCOMES) # 绘图 sns.countplot(x="outcomes_col", data=df, palette='Magma') plt.xticks(rotation=90) plt.ylabel('Amount') plt.xlabel('Outcomes') plt.title("Outcomes per Testing") plt.tight_layout() # 避免轴标签被截断 plt.show()
说明
- 移除了原代码中多余的
append操作,不会再生成无效样本干扰计数 - 补充了数据类型转换、分类命名统一、异常值映射逻辑,确保所有有效数据都能被正确统计
- 分类排列顺序完全符合你要求的规则
内容的提问来源于stack exchange,提问作者getting it
相关产品推荐
相关产品推荐

