Files
AIclinicalresearch/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Pivot列顺序优化总结.md
HaHafeng 1b53ab9d52 feat(aia): Complete AIA V2.0 with universal streaming capabilities
Major Changes:
- Add StreamingService with OpenAI Compatible format
- Upgrade Chat component V2 with Ant Design X integration
- Implement AIA module with 12 intelligent agents
- Update API routes to unified /api/v1 prefix
- Update system documentation

Backend (~1300 lines):
- common/streaming: OpenAI Compatible adapter
- modules/aia: 12 agents, conversation service, streaming integration
- Update route versions (RVW, PKB to v1)

Frontend (~3500 lines):
- modules/aia: AgentHub + ChatWorkspace (100% prototype restoration)
- shared/Chat: AIStreamChat, ThinkingBlock, useAIStream Hook
- Update API endpoints to v1

Documentation:
- AIA module status guide
- Universal capabilities catalog
- System overview updates
- All module documentation sync

Tested: Stream response verified, authentication working
Status: AIA V2.0 core completed (85%)
2026-01-14 19:15:01 +08:00

5.6 KiB
Raw Blame History

工具C - Pivot列顺åº<C3A5>ä¼˜åŒæ€»ç»“

📋 问题æ<CB9C><C3A6>è¿°

**用户需æ±?*:长宽转æ<C2AC>¢å<C2A2>Žï¼Œåˆ—çš„æŽåº<C3A5>应该与上传æ‡ä»¶æ—¶çš„列顺åº<C3A5>ä¿<C3A4>æŒ<C3A6>一致ã€?

**当å‰<C3A5>问题**:系统按字æ¯<C3A6>顺åº<C3A5>æŽåˆ—转æ<C2AC>¢å<C2A2>Žçš„列,导致顺åº<C3A5>与原æ‡ä»¶ä¸<C3A4>一致ã€?


🎯 è§£å†³æ¹æ¡ˆï¼šæ¹æ¡ˆA - Python端æŽåº?

核心æ€<EFBFBD>è·¯

  1. Node.jså<73>Žç«¯ä»Žsession获å<C2B7>*原始列顺åº?
  2. Node.jså<73>Žç«¯ä»Žæ•°æ<C2B0>®ä¸­æ<C2AD><C3A6>å<EFBFBD>**é€<C3A9>视列值的原å§é¡ºåº<C3A5>**ï¼ˆæŒ‰é¦æ¬¡å‡ºçŽ°é¡ºåº<C3A5>ï¼?
  3. ä¼ é€ç»™Python
  4. Python在pivotå<EFBFBD>Žï¼ŒæŒ‰åŽŸå§é¡ºåº<EFBFBD>é‡<EFBFBD>æŽåˆ

🛠�实现细节

1. Python端(pivot.py�

**æ°å¢žå<C5BE>æ•°**ï¼?

  • original_column_order: List[str]:原å§åˆ—顺åº<EFBFBD>(å¦['Record ID', 'Event Name', 'FMA', '体é‡<C3A9>', '收缩åŽ?, ...]ï¼?
  • pivot_value_order: List[str]:é€<EFBFBD>视列值的原å§é¡ºåº<EFBFBD>(å¦['基线', '1个月', '2个月', ...]ï¼?

**æŽåº<C3A5>逻è¾**ï¼?

if original_column_order:
    # 1. 索引列å§ç»ˆåœ¨æœ€å‰<C3A5>é<EFBFBD>¢
    final_cols = [index_column]
    
    # 2. 按原å§åˆ—顺åº<C3A5>添加转æ<C2AC>¢å<C2A2>Žçš„åˆ?
    for orig_col in original_column_order:
        if orig_col in value_columns:
            # 找出所有属于这个原列的新列
            related_cols = [c for c in df_pivot.columns if c.startswith(f'{orig_col}___')]
            
            # âœ?按é€<C3A9>视列的原å§é¡ºåº<C3A5>æŽåº<C3A5>
            if pivot_value_order:
                pivot_order_map = {val: idx for idx, val in enumerate(pivot_value_order)}
                related_cols_sorted = sorted(
                    related_cols,
                    key=lambda c: pivot_order_map.get(c.split('___')[1], 999)
                )
            else:
                related_cols_sorted = sorted(related_cols)
            
            final_cols.extend(related_cols_sorted)
    
    # 3. 添加未选æ©çš„列(ä¿<C3A4>æŒ<C3A6>原å§é¡ºåº<C3A5>)
    if keep_unused_columns:
        for orig_col in original_column_order:
            if orig_col in df_pivot.columns and orig_col not in final_cols:
                final_cols.append(orig_col)
    
    # 4. é‡<C3A9>æŽåˆ?
    df_pivot = df_pivot[final_cols]

2. Python端(main.py�

**PivotRequest模åž**ï¼?

class PivotRequest(BaseModel):
    # ... 原有字段 ...
    original_column_order: List[str] = []  # �新增
    pivot_value_order: List[str] = []  # �新增

调用pivot_long_to_wide�

result_df = pivot_long_to_wide(
    df,
    request.index_column,
    request.pivot_column,
    request.value_columns,
    request.aggfunc,
    request.column_mapping,
    request.keep_unused_columns,
    request.unused_agg_method,
    request.original_column_order,  # �新增
    request.pivot_value_order  # �新增
)

3. Node.jså<73>Žç«¯ï¼ˆQuickActionController.tsï¼?

**获å<C2B7>原å§åˆ—顺åº?*ï¼?

const originalColumnOrder = session.columns || [];

**获å<C2B7>é€<C3A9>视列值的原å§é¡ºåº<C3A5>**ï¼?

const pivotColumn = params.pivotColumn;
const seenPivotValues = new Set();
const pivotValueOrder: string[] = [];

for (const row of fullData) {
  const pivotValue = row[pivotColumn];
  if (pivotValue !== null && pivotValue !== undefined && !seenPivotValues.has(pivotValue)) {
    seenPivotValues.add(pivotValue);
    pivotValueOrder.push(String(pivotValue));
  }
}

ä¼ é€ç»™QuickActionServiceï¼?

executeResult = await quickActionService.executePivot(
  fullData, 
  params, 
  session.columnMapping,
  originalColumnOrder,  // �新增
  pivotValueOrder  // �新增
);

4. Node.jså<73>Žç«¯ï¼ˆQuickActionService.tsï¼?

**æ¹æ³•ç­¾å<C2BE><C3A5>**ï¼?

async executePivot(
  data: any[], 
  params: PivotParams, 
  columnMapping?: any[], 
  originalColumnOrder?: string[],  // �新增
  pivotValueOrder?: string[]  // �新增
): Promise<OperationResult>

ä¼ é€ç»™Pythonï¼?

const response = await axios.post(`${PYTHON_SERVICE_URL}/api/operations/pivot`, {
  // ... 原有å<E280B0>æ•° ...
  original_column_order: originalColumnOrder || [],  // �新增
  pivot_value_order: pivotValueOrder || [],  // �新增
});

📊 效果对比

修改å‰<EFBFBD>(按字æ¯<EFBFBD>顺åº<EFBFBD>)

Record ID | FMA___基线 | FMA___1个月 | 收缩åŽ___基线 | 收缩åŽ___1个月 | 体é‡<C3A9>___基线 | 体é‡<C3A9>___1个月
    �         �            �             �              �           �          �
  索引�     F开�       F开�          S开�拼音)     S开�       T开�      T开�

修改å<EFBFBD>Žï¼ˆæŒ‰åŽŸå§é¡ºåº<EFBFBD>)

Record ID | FMA___基线 | FMA___1个月 | 体é‡<C3A9>___基线 | 体é‡<C3A9>___1个月 | 收缩åŽ___基线 | 收缩åŽ___1个月
    �         �            �           �            �            �             �
  索引åˆ?   原æ‡ä»¶ç¬¬3åˆ?  原æ‡ä»¶ç¬¬3åˆ?  原æ‡ä»¶ç¬¬4åˆ?  原æ‡ä»¶ç¬¬4åˆ?  原æ‡ä»¶ç¬¬5åˆ?   原æ‡ä»¶ç¬¬5åˆ?

é€<EFBFBD>视值内部顺åº<EFBFBD>(按原å§å‡ºçŽ°é¡ºåº<EFBFBD>)

FMA___基线 | FMA___1个月 | FMA___2个月
    �          �            �
  首次出现    第二次出�   第三次出�
(而ä¸<C3A4>是按"1个月"ã€?2个月"ã€?基线"的字æ¯<C3A6>顺åº<C3A5>)

âœ?å¼€å<E282AC>完æˆ?

修改æ‡ä»¶æ¸…å<EFBFBD>

  1. �extraction_service/operations/pivot.py
  2. �extraction_service/main.py
  3. �backend/src/modules/dc/tool-c/controllers/QuickActionController.ts
  4. �backend/src/modules/dc/tool-c/services/QuickActionService.ts

优势

  • âœ?列顺åº<C3A5>与原æ‡ä»¶ä¸€è‡´ï¼ˆç”¨æˆ·ç†Ÿæ‰ï¼?
  • âœ?é€<C3A9>视值顺åº<C3A5>按时间顺åº<C3A5>(基线↸ªæœˆâ†?个月ï¼?
  • âœ?未选æ©çš„列也ä¿<C3A4>æŒ<C3A6>原å§é¡ºåº?
  • âœ?导出Excel时顺åº<C3A5>æ­£ç¡?

**å¼€å<E282AC>æ—¶é—?*ï¼?025-12-09
**状æ€?*:✅ 已完æˆ<C3A6>,等待æµè¯•