You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Kano分析脚本修改:多特征合并为单图展示需求

解决Kano分析多特征合并绘图问题

当前脚本为每个特征生成单独图表,需求改为在单张图中展示所有特征的SI/DSI结果点,并通过图例标注每个特征名称。以下是修改后的完整代码及关键调整说明:

关键修改点

  • 移除原单图绘制逻辑,改为先初始化全局画布,批量添加所有特征的散点
  • 新增数据收集步骤,汇总所有特征的SI、DSI值及名称
  • 统一设置图表样式、背景色块、双图例(Kano类别+特征名称),最后一次性保存并展示合并图

修改后的完整代码

# -*- coding: utf-8 -*-
"""
Spyder Editor
合并Kano分析所有特征到单张图
"""
# 读取数据
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import collections
import os
from matplotlib.patches import Patch

data = pd.read_excel(r'C:\Users\xxx\Nextcloud\03_Documents\xxx\data_kano.xlsx', header=0)
# 修正原代码:drop操作需重新赋值才生效
data = data.drop(index=0)
segment = list(range(0, len(data.columns)+1, 2))

store = []
for x in range(1, len(segment)):
    df = data.iloc[:, segment[x-1]:segment[x]].copy()
    store.append(df)

# Kano分类矩阵
eval_matrix = pd.DataFrame(
    {'#1': ['Q','R','R','R','R'],
     '#2': ['A','I','I','I','R'],
     '#3': ['A','I','I','I','R'],
     '#4': ['A','I','I','I','R'],
     '#5': ['O','M','M','M','Q']},
    index=['#1','#2','#3','#4','#5']
)

# 计算每个特征的Kano分类结果
result = pd.DataFrame()
for x in range(0, len(store)):
    Kano_score = []
    for y in range(len(store[x].iloc[:,0])):
        Kano_score.append(eval_matrix.loc[store[x].iloc[y,0], store[x].iloc[y,1]])
    pos_col = f'Feature {x+1}-1'  
    neg_col = f'Feature {x+1}-2' 
    res_col = f'Feature {x+1}-Result' 
    result[pos_col] = store[x].iloc[:,0].copy()
    result[neg_col] = store[x].iloc[:,1].copy()
    result[res_col] = Kano_score

# 满意度/不满意度系数计算函数
def SI(A: int, O: int, M: int, I: int) -> float:
    return float((A + O) / (A + O + M + I))

def DSI(A: int, O: int, M: int, I: int) -> float:
    return float((O + M) / (A + O + M + I) * -1)

# 汇总所有特征的SI、DSI值,同时导出Excel结果
feature_metrics = []
pos_cols = list(range(2, len(result.columns), 3))

os.makedirs('figures', exist_ok=True)
with pd.ExcelWriter('Kano_scoring_Ergebnisse.xlsx', engine="openpyxl") as writer:
    for idx, col in enumerate(pos_cols):
        feature_name = f'Feature {idx+1}'
        count = collections.Counter(result.iloc[:, col])
        df = pd.DataFrame.from_dict(count, orient='index', columns=['Score'])
        
        # 处理缺失类别,默认计数为0
        A = df.loc['A', 'Score'] if 'A' in df.index else 0
        O = df.loc['O', 'Score'] if 'O' in df.index else 0
        M = df.loc['M', 'Score'] if 'M' in df.index else 0
        I = df.loc['I', 'Score'] if 'I' in df.index else 0
        
        si_val = SI(A, O, M, I)
        dsi_val = DSI(A, O, M, I)
        
        df['SI'] = np.nan
        df['DSI'] = np.nan
        df.loc['A', 'SI'] = si_val
        df.loc['A', 'DSI'] = dsi_val
        
        df.to_excel(writer, sheet_name=feature_name)
        feature_metrics.append((feature_name, si_val, dsi_val))

# 绘制合并图
plt.figure(figsize=(10, 8))
ax = plt.axes()

# 绘制Kano分区背景色块
# 无差异区(蓝色)
plt.fill([0.0,0.0,0.5,0.5], [-0.0,-0.5,-0.5,-0.0], alpha=0.25, color="b")
# 魅力区(深绿)
plt.fill([0.5,0.5,1.0,1.0], [-0.0,-0.5,-0.5,-0.0], alpha=0.25, color="#036630")
# 一维区(黄色)
plt.fill([0.5,0.5,1.0,1.0], [-0.5,-1.0,-1.0,-0.5], alpha=0.25, color="y")
# 必备区(红色)
plt.fill([0.0,0.0,0.5,0.5], [-0.5,-1.0,-1.0,-0.5], alpha=0.25, color="r")

# 绘制所有特征的散点,自动分配差异化颜色
colors = plt.cm.tab10(np.linspace(0, 1, len(feature_metrics)))
for (name, si, dsi), color in zip(feature_metrics, colors):
    ax.scatter(si, dsi, color=color, label=name, s=80, zorder=5)

# 设置图表基础样式
ax.set(xlim=[0,1], ylim=[-1,0],
       xlabel='Functional (Satisfaction Coefficients CS+)',
       ylabel='Disfunctional (Dissatisfaction Coefficients CS-)',
       xticks=np.arange(0,1,0.1),
       yticks=np.arange(-1,0,0.1))
ax.set_title('Kano Analysis: All Features', size=16)
ax.grid(True)

# 加粗中间十字分隔线
gridlines = ax.yaxis.get_gridlines()
gridlines[5].set_color('k')
gridlines[5].set_linewidth(2.5)
gridlines = ax.xaxis.get_gridlines()
gridlines[5].set_color('k')
gridlines[5].set_linewidth(2.5)

# 添加双图例:Kano分区类别 + 特征名称
category_patches = [
    Patch(color="b", alpha=0.25, label="Indifferent"),
    Patch(color="#036630", alpha=0.25, label="Attractive"),
    Patch(color="y", alpha=0.25, label="One-Dimensional"),
    Patch(color="r", alpha=0.25, label="Must Be")
]

first_legend = ax.legend(handles=category_patches, bbox_to_anchor=(0.225, -0.3, 0.55, 0.5), 
                         loc='lower center', ncol=2, fontsize="small", framealpha=1)
ax.add_artist(first_legend)
ax.legend(loc='upper right', fontsize="small", title="Features")

plt.tight_layout()
plt.savefig('./figures/All_Features_Kano.jpg', bbox_inches='tight')
plt.show()

额外修正说明

  • 修复原代码中data.drop(index=0)未赋值导致首行未删除的问题
  • 处理部分特征缺失Kano类别计数的情况,避免KeyError
  • 使用tab10调色板自动为每个特征分配独特颜色,提升辨识度
  • 优化图例布局,同时展示Kano分区和特征名称,避免重叠遮挡

内容的提问来源于stack exchange,提问作者Karl Winter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 20:57:25