skills/ppt-station-skill/ppt_station/transformers/dataframe_ops.py
wangyitong a65adcc2e5 Initial commit: merged, deduplicated, and vetted skill collection
Sources: extracted from two upstream archives (skill-repo, skills-main),
merged with the following policy:

- 15 broken symlinks (pointing to /Users/jameslee/.cc-switch/skills or
  ../../.agents/skills on a foreign machine) discarded
- 3 real name collisions with identical content (ai-pair, ifind-http-api,
  zhipu-websearch) kept as one copy
- Functional overlaps deduped keeping the strongest variant:
  - docx family: kept docx (official, full toolchain) + docx-cn
    (GB/T 9704 Chinese official-document constants),
    dropped docx_writer (no scripts, name collided with docx)
  - humanizer family: kept humanizer-zh (6 zh reference docs),
    dropped humanizer (en, redundant for CN workflow)
- Skills that only ran in a foreign environment removed:
  ablemind-ops, app-publish, hlb-design-system, openclaw-adj-skill,
  claude-driver
- alphapai excluded from this public repo because its SKILL.md hard-coded
  live credentials

Result: 25 skills, 572 files, ~7.5 MB.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-13 14:47:12 +08:00

84 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
数据转换器
"""
from typing import Dict, List
import pandas as pd
from ppt_station.models.job import Transform, TransformOp
class DataFrameTransformer:
"""DataFrame 转换器"""
@staticmethod
def apply_transforms(
dfs: Dict[str, pd.DataFrame], transforms: Dict[str, Transform]
) -> Dict[str, pd.DataFrame]:
"""应用所有转换"""
result = dict(dfs)
for name, transform in (transforms or {}).items():
# 获取源数据
if isinstance(transform.from_, str):
source_df = result[transform.from_].copy()
elif isinstance(transform.from_, list):
# 多个数据源需要合并
source_dfs = [result[src].copy() for src in transform.from_]
source_df = source_dfs[0]
for df in source_dfs[1:]:
# 默认按索引合并
source_df = pd.concat([source_df, df], axis=1)
else:
raise ValueError(f"Invalid 'from' type: {type(transform.from_)}")
# 应用操作
for op in transform.ops:
source_df = DataFrameTransformer._apply_op(source_df, op)
result[name] = source_df
return result
@staticmethod
def _apply_op(df: pd.DataFrame, op: TransformOp) -> pd.DataFrame:
"""应用单个转换操作"""
if op.type == "groupby":
if not op.by or not op.agg:
raise ValueError("groupby requires 'by' and 'agg' parameters")
return df.groupby(op.by).agg(op.agg).reset_index()
elif op.type == "pivot":
if not op.index or not op.columns or not op.values:
raise ValueError("pivot requires 'index', 'columns', and 'values'")
return df.pivot(index=op.index, columns=op.columns, values=op.values)
elif op.type == "merge":
# merge 需要两个 DataFrame这里暂不实现
raise NotImplementedError("merge operation should be handled at higher level")
elif op.type == "compute":
if not op.expr or not op.output_col:
raise ValueError("compute requires 'expr' and 'output_col'")
# 使用 eval 计算表达式
df[op.output_col] = df.eval(op.expr)
return df
elif op.type == "filter":
if not op.condition:
raise ValueError("filter requires 'condition'")
return df.query(op.condition)
elif op.type == "sort":
if not op.sort_by:
raise ValueError("sort requires 'sort_by'")
return df.sort_values(op.sort_by, ascending=op.ascending)
elif op.type == "rename":
if not op.map:
raise ValueError("rename requires 'map'")
return df.rename(columns=op.map)
else:
raise ValueError(f"Unknown operation type: {op.type}")