2018.10.09 函数的参数(命名关键字参数)

命名关键字参数也就是调用函数时,只允许传入指定名称的参数。比如定义一个存储学生信息的函数,我们需要姓名、性别、年龄、专业等,但不需要女票的生日年龄等信息。则可以使用命名关键字参数的方法。

例如:

def stu(name,age,*,gender,major):

    pass

此时*后面的即为命名关键字,传参时只能传入gender和major

命名关键字调用时,必须有参数名。

例如

fun(xxd,24,gender='M',major='CS')

 

如果函数中已经有一个可变参数了,则只需要如下操作:

def stu(name,age,*grade,gender,major):

    pass试试发发发

 

import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns import os from matplotlib.gridspec import GridSpec from matplotlib.ticker import PercentFormatter # -------------------------- 全局配置 -------------------------- plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"] # 中文字体 plt.rcParams["axes.unicode_minus"] = False # 正确显示负号 plt. rcParams['font.sans–serif']=['Kaiti'] sns.set_theme(style="whitegrid", palette="deep") # 可视化主题 output_dir = "F:/大数据/第6章/杜邦分析图表" # 输出路径 os.makedirs(output_dir, exist_ok=True) # 自动创建目录 # -------------------------- 日期处理函数 -------------------------- def extract_year(date_value): """从'截止日期'列提取年份(支持多种格式)""" date_str = str(date_value).strip() if "-" in date_str: return int(date_str.split("-")[0]) # 处理2023-12-31 if "年" in date_str: return int(date_str.split("年")[0]) # 处理2023年12月 if len(date_str)>=4 and date_str.isdigit(): return int(date_str[:4]) # 处理20231231 return np.nan # -------------------------- 数据读取与清洗 -------------------------- def load_financial_data(file_path): """加载财务报表并处理日期列(返回带年份列的清洗后DataFrame)""" df = pd.read_excel(file_path, sheet_name=0) # 强制读取第一个工作表 if not isinstance(df, pd.DataFrame): raise TypeError(f"文件{file_path}读取失败,返回类型为{type(df)}") # 查找"截止日期"列(关键列) date_cols = [col for col in df.columns if "截止日期" in col] if not date_cols: raise ValueError(f"文件{file_path}未找到'截止日期'列") # 提取年份并清洗数据 df["年份"] = df[date_cols[0]].apply(extract_year) df = df[df["年份"].notna()].astype({"年份": int}) # 过滤无效年份并转换为整数 return df.sort_values("年份").reset_index(drop=True) # 按年份排序 # -------------------------- 列名动态匹配 -------------------------- def find_column(df, keywords): """动态匹配DataFrame中的列名(支持模糊匹配)""" for col in df.columns: if any(keyword in col for keyword in keywords): return col raise ValueError(f"未找到包含以下关键词的列: {keywords}") # -------------------------- 杜邦分析核心逻辑 -------------------------- def dupont_analysis(balance_sheet_path, income_statement_path): # 加载并清洗数据 bs = load_financial_data(balance_sheet_path) # 资产负债表 is_ = load_financial_data(income_statement_path) # 利润表 # 匹配关键列(支持列名变体) bs_assets = find_column(bs, ["资产总计", "资产合计"]) # 资产总计列 bs_equity = find_column(bs, ["所有者权益", "股东权益", "净资产"]) # 所有者权益列 is_revenue = find_column(is_, ["营业收入", "营业总收入"]) # 营业收入列 is_net_profit = find_column(is_, ["净利润", "归属于母公司", "归母净利润"]) # 净利润列 # 按年份合并数据(仅保留共同年份) merged_df = bs[["年份", bs_assets, bs_equity]].merge( is_[["年份", is_revenue, is_net_profit]], on="年份", how="inner" ) merged_df.columns = ["年份", "资产总计", "所有者权益合计", "营业收入", "净利润"] # 统一列名 # 计算杜邦指标 merged_df["ROE"] = (merged_df["净利润"] / merged_df["所有者权益合计"]) * 100 # 净资产收益率 merged_df["净利润率"] = (merged_df["净利润"] / merged_df["营业收入"]) * 100 # 净利润率 merged_df["平均总资产"] = (merged_df["资产总计"] + merged_df["资产总计"].shift(1)) / 2 # 平均总资产 merged_df["总资产周转率"] = merged_df["营业收入"] / merged_df["平均总资产"].fillna(merged_df["资产总计"]) # 总资产周转率(处理首年) merged_df["权益乘数"] = merged_df["资产总计"] / merged_df["所有者权益合计"] # 权益乘数 merged_df["ROA"] = merged_df["净利润率"] * merged_df["总资产周转率"] # 总资产收益率 return merged_df.dropna() # 过滤缺失值 # -------------------------- 可视化输出(完整标题版) -------------------------- def visualize_duPont(df): # -------------------- 图表1:杜邦核心指标趋势图 -------------------- fig = plt.figure(figsize=(16, 10), constrained_layout=True) fig.suptitle("格力电器杜邦分析核心指标趋势(2018-2023)", fontsize=18, fontweight="bold", y=1.02) # 主标题 gs = GridSpec(2, 2, figure=fig, height_ratios=[2, 1]) # 子图布局(2行2列) # ROE趋势(主指标) ax1 = fig.add_subplot(gs[0, :]) sns.lineplot(data=df, x="年份", y="ROE", marker="o", linewidth=3, color="#E64B35", ax=ax1) ax1.set_title("核心指标:净资产收益率(ROE)", fontsize=16, pad=15) # 子标题 ax1.set_ylabel("ROE(%)", fontsize=14) ax1.yaxis.set_major_formatter(PercentFormatter()) ax1.grid(linestyle="--", alpha=0.6) # 添加数据标签 for x, y in df[["年份", "ROE"]].values: ax1.text(x, y+0.5, f"{y:.1f}%", ha="center", fontsize=12, color="#E64B35") # 净利润率趋势(柱状图) ax2 = fig.add_subplot(gs[1, 0]) sns.barplot(data=df, x="年份", y="净利润率", color="#4DBBD5", ax=ax2) ax2.set_title("盈利能力:净利润率", fontsize=15, pad=12) # 子标题 ax2.set_ylabel("净利润率(%)", fontsize=13) ax2.yaxis.set_major_formatter(PercentFormatter()) # 添加柱状图标签 for p in ax2.patches: height = p.get_height() ax2.text(p.get_x()+p.get_width()/2., height+0.2, f"{height:.1f}%", ha="center", fontsize=11) # 总资产周转率趋势(线图) ax3 = fig.add_subplot(gs[1, 1]) sns.lineplot(data=df, x="年份", y="总资产周转率", marker="s", linewidth=2.5, color="#3C5488", ax=ax3) ax3.set_title("运营效率:总资产周转率", fontsize=15, pad=12) # 子标题 ax3.set_ylabel("周转率(次)", fontsize=13) ax3.grid(linestyle="--", alpha=0.6) # 添加趋势阴影 ax3.fill_between(df["年份"], df["总资产周转率"], alpha=0.1, color="#3C5488") plt.savefig(f"{output_dir}/杜邦核心指标趋势图.png", dpi=300, bbox_inches="tight") # 保存时自动调整边界 # -------------------- 图表2:ROE分解瀑布图 -------------------- fig, ax = plt.subplots(figsize=(14, 8)) base_year = df["年份"].min() current_year = df["年份"].max() ax.set_title(f"{base_year}年-{current_year}年ROE驱动因素分解", fontsize=18, fontweight="bold", pad=20) # 主标题 # 计算各因素贡献值 base = df[df["年份"] == base_year].iloc[0] current = df[df["年份"] == current_year].iloc[0] factors = [ ("基年ROE", base["ROE"], "#3C5488"), ("净利润率贡献", base["ROE"]*(current["净利润率"]/base["净利润率"]-1), "#4DBBD5"), ("总资产周转率贡献", base["ROE"]*(current["净利润率"]/base["净利润率"])*(current["总资产周转率"]/base["总资产周转率"]-1), "#00A087"), ("权益乘数贡献", base["ROE"]*(current["净利润率"]/base["净利润率"])*(current["总资产周转率"]/base["总资产周转率"])*(current["权益乘数"]/base["权益乘数"]-1), "#F39B7F"), ("当前年ROE", current["ROE"], "#E64B35"), ] # 绘制瀑布图 y_pos = np.arange(len(factors)) bars = ax.barh(y_pos, [f[1] for f in factors], color=[f[2] for f in factors], edgecolor="black", height=0.6) ax.set_yticks(y_pos) ax.set_yticklabels([f[0] for f in factors], fontsize=12) ax.set_xlabel("ROE贡献值(%)", fontsize=14) ax.xaxis.set_major_formatter(PercentFormatter()) # 添加数值标签 for bar, (name, value, _) in zip(bars, factors): ax.text(bar.get_width()+0.5 if value>0 else bar.get_width()-1.5, bar.get_y()+bar.get_height()/2, f"{value:.1f}%", va="center", fontsize=11) plt.savefig(f"{output_dir}/ROE驱动因素分解图.png", dpi=300, bbox_inches="tight") # -------------------- 图表3:指标相关性热力图 -------------------- fig, ax = plt.subplots(figsize=(12, 9)) ax.set_title("杜邦分析核心指标相关性矩阵", fontsize=18, fontweight="bold", pad=25) # 主标题 corr = df[["ROE", "净利润率", "总资产周转率", "权益乘数", "ROA"]].corr().round(2) # 绘制热力图 sns.heatmap(corr, annot=True, cmap="coolwarm", vmin=-1, vmax=1, linewidths=0.5, annot_kws={"fontsize": 14}, square=True, cbar_kws={"shrink": 0.8, "label": "相关系数(r)"}) ax.set_xticklabels(ax.get_xticklabels(), rotation=45, ha="right", fontsize=12) ax.set_yticklabels(ax.get_yticklabels(), rotation=0, fontsize=12) plt.savefig(f"{output_dir}/指标相关性热力图.png", dpi=300, bbox_inches="tight") print(f"所有完整图表已保存至:{output_dir}") # -------------------------- 主程序 -------------------------- if __name__ == "__main__": try: # 替换为实际文件路径(确保Excel文件包含"截止日期"列) balance_sheet_path = "F:/大数据/第6章/格力资产负债表.xlsx" income_statement_path = "F:/大数据/第6章/格力利润表.xlsx" # 执行杜邦分析 analysis_df = dupont_analysis(balance_sheet_path, income_statement_path) # 保存分析结果(保留2位小数) analysis_df.round(2).to_excel(f"{output_dir}/格力杜邦分析数据.xlsx", index=False) print(f"分析数据已保存至:{output_dir}/格力杜邦分析数据.xlsx") # 生成完整图表 visualize_duPont(analysis_df) except Exception as e: print(f"程序运行错误: {str(e)}") 运行代码
最新发布
06-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值