R_4th 图形的文本标注

本文介绍了如何在R语言中进行图形的文本标注,包括使用`text()`和`mtext()`函数。`attach()`用于将数据框加载到内存,便于操作;`text()`在图形内部添加文本,而`mtext()`则在图形边界添加。关键参数包括位置坐标、文本、位置选项(pos/side)、缩放比例和文字样式等。

R_4th 图形的文本标注

 

attach是将数据添加上内存中,一般用于数据框,添加之后就可以直接提取数据框的,但是一般用完都会detach()删除掉

 

text () 可以在绘图区进行文本添加

mtext()可以在图形的四个边界添加文本

 

其主要参数有

text : location 、“text ” 、 pos

mtext : “text” 、 side 、 line = n

 

location可以定义文本位置参数, 可以为一对x、y 坐标,也可以通过locator(1)进行鼠标定位

pos : 文本位置 一般 1= 下, 2 = 左, 3= 上,4= 右 。

side : 同理, mtext的位置,和pos一样。

 

其他还有 cex 缩放大小、 font文字样式 1= 常规、2=粗体、3=斜体 4= 粗斜体

 

比如以下代码

 

> attach(mtcars)

> plot(wt,mpg,main = "Mileage VS. Car weight",xlab= "Weight", ylab = "Mileage",pch = 18, col = "blue")
> text(wt,mpg,row.names(mtcars),cex=0.6,pos =4, col ="red")
> detach(mtcars)
 
第一行attach 
第二行创建一个散点图
第三行文本标注,由于是在图上标注,所以为text row.namesmtcars)、 cex缩放0.6  pos 4 右边。所以就有了下图。
 
第四行 detach删除掉数据。

 

书中同样还有一定的补充:

> opar <- par(no.readonly = TRUE)
> par(cex= 1.5)
> plot(1:7 , 1:7, type = "n")
> text(3,3,"Example of default text")
> text(4,4,family = "mono" , "Example of mono-spaced text")
> text(5,5,family= "serif", "Example of serif text")
> par(opar)
> text(locator(1),"sb")
 
par函数设定环境 cex = 1.5
plot创建坐标轴,text33)、(44)、(55)可以定义文本的坐标轴位置。在结束后尝试用locator1)可以使用鼠标来拖动文本的位置,如下图所示。

 

 

 

import numpy as np import matplotlib.pyplot as plt from matplotlib import rcParams # 设置中文字体 rcParams['font.sans-serif'] = ['SimHei'] rcParams['axes.unicode_minus'] = False class CoolantTemperatureModel: def __init__(self): # 给定参数 self.k1 = 0.05 # 热交换系数 (s^-1) self.Tamb = 25 # 环境温度 (°C) self.k2 = 0.001 # 功率系数 (°C·s^-1·W^-1) self.P0 = 1e-7 # 平均功率 (W) self.w = np.pi / 100 # 角频率 (s^-1) self.tmax = 500 # 反应堆运行时间 (s) self.T0 = 50 # 初始温度 (°C) def power_function(self, t): """反应堆功率函数""" if t <= self.tmax: return self.P0 * (1 + np.sin(self.w * t)) else: return 0.0 def derivative(self, t, T): """常微分方程右边函数""" P_t = self.power_function(t) return -self.k1 * (T - self.Tamb) + self.k2 * P_t def runge_kutta_4th(self, t_start, t_end, h): """四阶Runge-Kutta方法求解""" n_steps = int((t_end - t_start) / h) + 1 t_values = np.linspace(t_start, t_end, n_steps) T_values = np.zeros(n_steps) T_values[0] = self.T0 for i in range(n_steps - 1): t = t_values[i] T = T_values[i] k1 = h * self.derivative(t, T) k2 = h * self.derivative(t + h/2, T + k1/2) k3 = h * self.derivative(t + h/2, T + k2/2) k4 = h * self.derivative(t + h, T + k3) T_values[i+1] = T + (k1 + 2*k2 + 2*k3 + k4) / 6 return t_values, T_values def solve_and_plot(self): """求解并绘制结果""" # 求解微分方程 t_values, T_values = self.runge_kutta_4th(0, 1000, 1) # 输出特定时刻的温度值 output_times = [100, 300, 500, 700, 900] print("特定时刻冷却剂温度值:") for time in output_times: idx = np.argmin(np.abs(t_values - time)) print(f"t = {time}s: T = {T_values[idx]:.4f}°C") # 绘制温度变化曲线 plt.figure(figsize=(12, 8)) # 主温度曲线 plt.plot(t_values, T_values, 'b-', linewidth=2, label='冷却剂温度') # 标记关键点 for time in output_times: idx = np.argmin(np.abs(t_values - time)) plt.plot(t_values[idx], T_values[idx], 'ro', markersize=8) plt.annotate(f'({time}s, {T_values[idx]:.2f}°C)', xy=(t_values[idx], T_values[idx]), xytext=(10, 10), textcoords='offset points', bbox=dict(boxstyle='round,pad=0.3', facecolor='yellow', alpha=0.7)) # 添加反应堆运行区域标记 plt.axvline(x=self.tmax, color='r', linestyle='--', linewidth=2, label=f'反应堆停止时间 (t={self.tmax}s)') plt.axhline(y=self.Tamb, color='g', linestyle='--', linewidth=2, label=f'环境温度 ({self.Tamb}°C)') # 设置图形属性 plt.xlabel('时间 (s)', fontsize=12) plt.ylabel('温度 (°C)', fontsize=12) plt.title('核动力船舶冷却剂温度随时间变化曲线', fontsize=14) plt.legend(fontsize=10) plt.grid(True, alpha=0.3) plt.xlim(0, 1000) # 添加区域标注 plt.text(250, 35, '反应堆运行期间', fontsize=12, bbox=dict(boxstyle='round,pad=0.5', facecolor='lightblue', alpha=0.5)) plt.text(750, 35, '反应堆停止后', fontsize=12, bbox=dict(boxstyle='round,pad=0.5', facecolor='lightgreen', alpha=0.5)) plt.tight_layout() plt.show() return t_values, T_values def parameter_sensitivity_analysis(self): """参数敏感性分析""" original_k1 = self.k1 original_P0 = self.P0 # 测试不同的k1值 k1_values = [0.02, 0.05, 0.1] plt.figure(figsize=(15, 5)) plt.subplot(1, 2, 1) for k1 in k1_values: self.k1 = k1 t_vals, T_vals = self.runge_kutta_4th(0, 1000, 1) plt.plot(t_vals, T_vals, linewidth=2, label=f'k1 = {k1}') plt.xlabel('时间 (s)') plt.ylabel('温度 (°C)') plt.title('不同热交换系数k1对温度的影响') plt.legend() plt.grid(True, alpha=0.3) # 测试不同的P0值 self.k1 = original_k1 # 恢复原始k1值 P0_values = [5e-8, 1e-7, 2e-7] plt.subplot(1, 2, 2) for P0 in P0_values: self.P0 = P0 t_vals, T_vals = self.runge_kutta_4th(0, 1000, 1) plt.plot(t_vals, T_vals, linewidth=2, label=f'P0 = {P0:.1e}') plt.xlabel('时间 (s)') plt.ylabel('温度 (°C)') plt.title('不同平均功率P0对温度的影响') plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.show() # 恢复原始参数 self.k1 = original_k1 self.P0 = original_P0 # 运行主程序 if __name__ == "__main__": model = CoolantTemperatureModel() print("=" * 60) print("核动力船舶冷却剂温度变化模型分析") print("=" * 60) # 求解并绘制结果 t_values, T_values = model.solve_and_plot() print("\n" + "=" * 60) print("参数敏感性分析") print("=" * 60) # 参数敏感性分析 model.parameter_sensitivity_analysis()
最新发布
10-23
# LBMA(伦敦金银市场协会)官网:https://www.lbma.org.uk/cn/prices-and-data#/ # 黄金: https://prices.lbma.org.uk/json/gold_pm.json?r=854633265 # 白银: https://prices.lbma.org.uk/json/silver.json?r=65231548 # import json from datetime import datetime import matplotlib.dates as mdates import matplotlib.pyplot as plt import pandas as pd import requests # 设置Matplotlib全局参数 plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定中文字体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 text_fontsize = 10 ryear = '2000' rdate = ryear + '0101' # 1.绘制金银价格图,使用twinx()创建,共用x轴但不同y轴的图表 def draw_gold_and_silver_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df['date'] y1 = df['gold'] y2 = df['silver'] fig, ax1 = plt.subplots(figsize=(10, 6)) fig.set_facecolor('antiquewhite') ax1.set_facecolor('antiquewhite') # 第一个y轴(左侧黄金) ax1.plot(x, y1, label='黄金', color='darkgoldenrod') ax1.set_ylabel('黄金(美元/盎司)') y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha='right', va='center', fontsize=10, color='darkgoldenrod') ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-20, y1.iloc[y1_min_index], ha='left', va='center', fontsize=10, color='darkgoldenrod') # 创建第二个y轴(右侧白银,共用x轴) ax2 = ax1.twinx() ax2.plot(x, y2, label='白银', color='gray') ax2.set_ylabel('白银(美元/盎司)') y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax2.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], y2.iloc[y2_max_index], ha='left', va='center', fontsize=10, color='gray') ax2.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, y2.iloc[y2_min_index], ha='right', va='center', fontsize=10, color='gray') # 添加标题和坐标轴标签 #ax1.tick_params(axis='y', labelcolor='gray') ax1.set_title(f'{ryear}-2025年黄金、白银走势对比图') ax1.set_xlabel('年份') # 合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left') # x轴比例刻度 ax1.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 2.绘制金银比图表 def draw_gold_silver_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df['date'] y = df['ratio'] y_70 = df['ratio_70th'] y_30 = df['ratio_30th'] fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor('antiquewhite') ax.set_facecolor('antiquewhite') # 金银比图例、最高点、最低点 ax.plot(x, y, label='金银比', color='blue') max_index = y.idxmax() min_index = y.idxmin() ax.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha='left', va='center', fontsize=10, color='blue') ax.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha='left', va='center', fontsize=10, color='blue') # 70分位值 ax.plot(x, y_70, label='70分位值', color='red') ax.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha='left', va='center', fontsize=10, color='red') # 30分位值 ax.plot(x, y_30, label='30分位值', color='green') ax.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha='left', va='center', fontsize=10, color='green') # 添加标题和x轴标签 ax.set_ylabel('金银比(黄金价格/白银价格)') ax.set_title(f'{ryear}-2025年金银比走势图') ax.set_xlabel('年份') # 图例 lines, labels = ax.get_legend_handles_labels() ax.legend(lines, labels, loc='upper left') # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 3.绘制金银和金银比总图表,共用x轴,金银使用一个y轴,金银比使用另一个y轴 def draw_gold_silver_and_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df['date'] y1 = df['gold'] y2 = df['silver_cv'] _y2 = df['silver'] y = df['ratio'] y_70 = df['ratio_70th'] y_30 = df['ratio_30th'] # 1.创建坐标轴,设置背景色 fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor('antiquewhite') ax.set_facecolor('antiquewhite') ax1 = ax ############################################################## # 2.左侧y轴 # 黄金价格 ax1.plot(x, y1, label='黄金', color='darkgoldenrod') y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha='right', va='center', fontsize=text_fontsize, color='darkgoldenrod') ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-50, y1.iloc[y1_min_index], ha='center', va='center', fontsize=text_fontsize, color='darkgoldenrod') # 白银价格 ax1.plot(x, y2, label='白银', color='gray') y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax1.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], _y2.iloc[y2_max_index], ha='left', va='center', fontsize=text_fontsize, color='gray') ax1.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, _y2.iloc[y2_min_index], ha='left', va='center', fontsize=text_fontsize, color='gray') ############################################################## # 3.创建右侧y轴,共用x轴 ax2 = ax1.twinx() ############################################################## # 4.金银比图例、最高点、最低点 ax2.plot(x, y, label='金银比', color='blue', linewidth=0.5) max_index = y.idxmax() min_index = y.idxmin() ax2.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha='left', va='center', fontsize=text_fontsize, color='blue') ax2.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha='left', va='center', fontsize=text_fontsize, color='blue') # 70分位值 ax2.plot(x, y_70, label='70分位值', color='red', linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha='left', va='center', fontsize=text_fontsize, color='red') # 30分位值 ax2.plot(x, y_30, label='30分位值', color='green', linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha='left', va='center', fontsize=text_fontsize, color='green') ############################################################## # 5.添加标题和xy轴标签 ax1.set_ylabel('价格') ax2.set_ylabel('金银比(黄金价格/白银价格)') ax1.set_title(f'{ryear}-2025年黄金、白银及金银比走势对比图') ax1.set_xlabel('年份') ############################################################## # 6.合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left') # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # # 处理原始json数据,转换成pandas DataFrame # # 伦敦金银 gold.json/silver.json:v对应'USD', 'GBP', 'EUR' 美元/英镑/欧元三种计价 # { # "is_cms_locked": 0, # "d": "2025-09-25", # "v": [3730.75, 2790.6, 3193.52] # } # #添加自己动获取数据 def download_data(url, filename): try: response = requests.get(url) with open(filename, 'wb') as f: f.write(response.content) print(f"已下载: {filename}") except Exception as e: print(f"下载失败: {e}") raise # def process_json(filename, cname): fd = open(filename, 'r') data = json.load(fd) fd.close() # 创建 DataFrame df = pd.json_normalize(data) # 增加列 split_cols = df['v'].apply(pd.Series) split_cols.columns = ['USD', 'GBP', 'EUR'] # 删除列 axis=1 df.drop(['is_cms_locked', 'v'], axis=1, inplace=True) df = pd.concat([df, split_cols['USD']], axis=1) # 修改名称 df = df.rename(columns={'d':'date', 'USD':cname}) df['date'] = pd.to_datetime(df['date']) df.set_index('date', inplace=True) # 筛选数据 start_date = datetime.strptime(rdate, "%Y%m%d") df = df[(df.index >= start_date)] df.reset_index(inplace=True) return df # 重组连接两张数据表 def recombine_data_from_json(): # 1.处理黄金数据: df_gold = process_json('gold.json', 'gold') # 2.处理白银数据: df_silver = process_json('silver.json', 'silver') # 3.连接两张表 # on: on​:指定合并的列名(两表列名相同时) # ​left_on/right_on​:左右表列名不同时使用,如:date1,date2 # how​:连接方式 # 'inner':只保留两表都有的日期(默认) # 'outer':保留所有日期,缺失值填NaN # 'left':保留左表所有日期 # 'right':保留右表所有日期 # ​suffixes​:列名冲突时的后缀(默认('x', 'y')) df = pd.merge(df_gold, df_silver, on='date', how='inner', suffixes=('_df1', '_df2')) # 4.以黄金价格作为基准,白银价格按照涨幅等比例转换。 df['silver_cv'] = round(df['silver'] * df['gold'].iloc[0] / df['silver'].iloc[0], 2) # 5.计算金银比 df['ratio'] = round(df['gold'] / df['silver'], 2) # 6.计算百分比分位值 df['ratio_70th'] = round(df['ratio'].quantile(0.7), 2) df['ratio_30th'] = round(df['ratio'].quantile(0.3), 2) # 7.写入csv文件 df.to_csv("gsr.csv") print(df) return df #if __name__ == "__main__": # 1.首先进入LMBA官网,使用浏览器下载原始json文件,python代码省略此部分。 # 或者,在cmd窗口执行如下命令: # 黄金:curl "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" -o gold.json # 白银:curl "https://prices.lbma.org.uk/json/silver.json?r=65231548" -o silver.json # 2.从json中提取数据, # df = recombine_data_from_json() # 3.可生成以下三类图表: # 黄金白银价格走势图 #draw_gold_and_silver_graph(df) # 金银比走势图 #draw_gold_silver_ratio_graph(df) # 组合叠加图 #draw_gold_silver_and_ratio_graph(df) #添加表格输出功能 def print_comparison_table(df): """打印金银比对比表格""" # 创建摘要表格 summary = pd.DataFrame({ '指标': ['黄金均价(USD)', '白银均价(USD)', '金银比均值', '70分位值', '30分位值'], '数值': [ df['gold'].mean(), df['silver'].mean(), df['ratio'].mean(), df['ratio_70th'].iloc[0], df['ratio_30th'].iloc[0] ] }) # 格式化输出 print("\n" + "=" * 50) print(f"{ryear}-2025年金银市场对比分析") print("=" * 50) print(summary.to_string(index=False)) # 添加时间序列表格 print("\n近期价格趋势:") print(df[['date', 'gold', 'silver', 'ratio']].tail(10).to_string(index=False)) if __name__ == "__main__": # 自动下载数据 gold_url = "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" silver_url = "https://prices.lbma.org.uk/json/silver.json?r=65231548" download_data(gold_url, "gold.json") download_data(silver_url, "silver.json") # 处理数据 df = recombine_data_from_json() # 输出对比表格 print_comparison_table(df) # 新增表格输出 # 生成图表(可选) draw_gold_silver_and_ratio_graph(df) # LBMA(伦敦金银市场协会)官网:https://www.lbma.org.uk/cn/prices-and-data#/ # 黄金: https://prices.lbma.org.uk/json/gold_pm.json?r=854633265 # 白银: https://prices.lbma.org.uk/json/silver.json?r=65231548 # import json from datetime import datetime import matplotlib.dates as mdates import matplotlib.pyplot as plt import pandas as pd import requests # 设置Matplotlib全局参数 plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定中文字体 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题 text_fontsize = 10 ryear = '2000' rdate = ryear + '0101' # 1.绘制金银价格图,使用twinx()创建,共用x轴但不同y轴的图表 def draw_gold_and_silver_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df['date'] y1 = df['gold'] y2 = df['silver'] fig, ax1 = plt.subplots(figsize=(10, 6)) fig.set_facecolor('antiquewhite') ax1.set_facecolor('antiquewhite') # 第一个y轴(左侧黄金) ax1.plot(x, y1, label='黄金', color='darkgoldenrod') ax1.set_ylabel('黄金(美元/盎司)') y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha='right', va='center', fontsize=10, color='darkgoldenrod') ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-20, y1.iloc[y1_min_index], ha='left', va='center', fontsize=10, color='darkgoldenrod') # 创建第二个y轴(右侧白银,共用x轴) ax2 = ax1.twinx() ax2.plot(x, y2, label='白银', color='gray') ax2.set_ylabel('白银(美元/盎司)') y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax2.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], y2.iloc[y2_max_index], ha='left', va='center', fontsize=10, color='gray') ax2.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, y2.iloc[y2_min_index], ha='right', va='center', fontsize=10, color='gray') # 添加标题和坐标轴标签 #ax1.tick_params(axis='y', labelcolor='gray') ax1.set_title(f'{ryear}-2025年黄金、白银走势对比图') ax1.set_xlabel('年份') # 合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left') # x轴比例刻度 ax1.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 2.绘制金银比图表 def draw_gold_silver_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df['date'] y = df['ratio'] y_70 = df['ratio_70th'] y_30 = df['ratio_30th'] fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor('antiquewhite') ax.set_facecolor('antiquewhite') # 金银比图例、最高点、最低点 ax.plot(x, y, label='金银比', color='blue') max_index = y.idxmax() min_index = y.idxmin() ax.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha='left', va='center', fontsize=10, color='blue') ax.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha='left', va='center', fontsize=10, color='blue') # 70分位值 ax.plot(x, y_70, label='70分位值', color='red') ax.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha='left', va='center', fontsize=10, color='red') # 30分位值 ax.plot(x, y_30, label='30分位值', color='green') ax.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha='left', va='center', fontsize=10, color='green') # 添加标题和x轴标签 ax.set_ylabel('金银比(黄金价格/白银价格)') ax.set_title(f'{ryear}-2025年金银比走势图') ax.set_xlabel('年份') # 图例 lines, labels = ax.get_legend_handles_labels() ax.legend(lines, labels, loc='upper left') # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # 3.绘制金银和金银比总图表,共用x轴,金银使用一个y轴,金银比使用另一个y轴 def draw_gold_silver_and_ratio_graph(df): # 标注偏移量 xoffset = +pd.Timedelta(weeks=2) # 设置x,y数据 x = df['date'] y1 = df['gold'] y2 = df['silver_cv'] _y2 = df['silver'] y = df['ratio'] y_70 = df['ratio_70th'] y_30 = df['ratio_30th'] # 1.创建坐标轴,设置背景色 fig, ax = plt.subplots(figsize=(10, 6)) fig.set_facecolor('antiquewhite') ax.set_facecolor('antiquewhite') ax1 = ax ############################################################## # 2.左侧y轴 # 黄金价格 ax1.plot(x, y1, label='黄金', color='darkgoldenrod') y1_max_index = y1.idxmax() y1_min_index = y1.idxmin() ax1.text(x[y1_max_index]-xoffset, y1.iloc[y1_max_index], y1.iloc[y1_max_index], ha='right', va='center', fontsize=text_fontsize, color='darkgoldenrod') ax1.text(x[y1_min_index]+xoffset, y1.iloc[y1_min_index]-50, y1.iloc[y1_min_index], ha='center', va='center', fontsize=text_fontsize, color='darkgoldenrod') # 白银价格 ax1.plot(x, y2, label='白银', color='gray') y2_max_index = y2.idxmax() y2_min_index = y2.idxmin() ax1.text(x[y2_max_index]+xoffset, y2.iloc[y2_max_index], _y2.iloc[y2_max_index], ha='left', va='center', fontsize=text_fontsize, color='gray') ax1.text(x[y2_min_index], y2.iloc[y2_min_index]-0.5, _y2.iloc[y2_min_index], ha='left', va='center', fontsize=text_fontsize, color='gray') ############################################################## # 3.创建右侧y轴,共用x轴 ax2 = ax1.twinx() ############################################################## # 4.金银比图例、最高点、最低点 ax2.plot(x, y, label='金银比', color='blue', linewidth=0.5) max_index = y.idxmax() min_index = y.idxmin() ax2.text(x[max_index]+xoffset, y.iloc[max_index], y.iloc[max_index], ha='left', va='center', fontsize=text_fontsize, color='blue') ax2.text(x[min_index]+xoffset, y.iloc[min_index], y.iloc[min_index], ha='left', va='center', fontsize=text_fontsize, color='blue') # 70分位值 ax2.plot(x, y_70, label='70分位值', color='red', linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_70.iloc[0], y_70.iloc[0], ha='left', va='center', fontsize=text_fontsize, color='red') # 30分位值 ax2.plot(x, y_30, label='30分位值', color='green', linewidth=0.5) ax2.text(x[x.count()-1]+xoffset, y_30.iloc[0], y_30.iloc[0], ha='left', va='center', fontsize=text_fontsize, color='green') ############################################################## # 5.添加标题和xy轴标签 ax1.set_ylabel('价格') ax2.set_ylabel('金银比(黄金价格/白银价格)') ax1.set_title(f'{ryear}-2025年黄金、白银及金银比走势对比图') ax1.set_xlabel('年份') ############################################################## # 6.合并图例 lines1, labels1 = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines1 + lines2, labels1 + labels2, loc='upper left') # x轴比例刻度 ax.xaxis.set_major_locator(mdates.YearLocator(1)) plt.show() # # 处理原始json数据,转换成pandas DataFrame # # 伦敦金银 gold.json/silver.json:v对应'USD', 'GBP', 'EUR' 美元/英镑/欧元三种计价 # { # "is_cms_locked": 0, # "d": "2025-09-25", # "v": [3730.75, 2790.6, 3193.52] # } # #添加自己动获取数据 def download_data(url, filename): try: response = requests.get(url) with open(filename, 'wb') as f: f.write(response.content) print(f"已下载: {filename}") except Exception as e: print(f"下载失败: {e}") raise # def process_json(filename, cname): fd = open(filename, 'r') data = json.load(fd) fd.close() # 创建 DataFrame df = pd.json_normalize(data) # 增加列 split_cols = df['v'].apply(pd.Series) split_cols.columns = ['USD', 'GBP', 'EUR'] # 删除列 axis=1 df.drop(['is_cms_locked', 'v'], axis=1, inplace=True) df = pd.concat([df, split_cols['USD']], axis=1) # 修改名称 df = df.rename(columns={'d':'date', 'USD':cname}) df['date'] = pd.to_datetime(df['date']) df.set_index('date', inplace=True) # 筛选数据 start_date = datetime.strptime(rdate, "%Y%m%d") df = df[(df.index >= start_date)] df.reset_index(inplace=True) return df # 重组连接两张数据表 def recombine_data_from_json(): # 1.处理黄金数据: df_gold = process_json('gold.json', 'gold') # 2.处理白银数据: df_silver = process_json('silver.json', 'silver') # 3.连接两张表 # on: on​:指定合并的列名(两表列名相同时) # ​left_on/right_on​:左右表列名不同时使用,如:date1,date2 # how​:连接方式 # 'inner':只保留两表都有的日期(默认) # 'outer':保留所有日期,缺失值填NaN # 'left':保留左表所有日期 # 'right':保留右表所有日期 # ​suffixes​:列名冲突时的后缀(默认('x', 'y')) df = pd.merge(df_gold, df_silver, on='date', how='inner', suffixes=('_df1', '_df2')) # 4.以黄金价格作为基准,白银价格按照涨幅等比例转换。 df['silver_cv'] = round(df['silver'] * df['gold'].iloc[0] / df['silver'].iloc[0], 2) # 5.计算金银比 df['ratio'] = round(df['gold'] / df['silver'], 2) # 6.计算百分比分位值 df['ratio_70th'] = round(df['ratio'].quantile(0.7), 2) df['ratio_30th'] = round(df['ratio'].quantile(0.3), 2) # 7.写入csv文件 df.to_csv("gsr.csv") print(df) return df #if __name__ == "__main__": # 1.首先进入LMBA官网,使用浏览器下载原始json文件,python代码省略此部分。 # 或者,在cmd窗口执行如下命令: # 黄金:curl "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" -o gold.json # 白银:curl "https://prices.lbma.org.uk/json/silver.json?r=65231548" -o silver.json # 2.从json中提取数据, # df = recombine_data_from_json() # 3.可生成以下三类图表: # 黄金白银价格走势图 #draw_gold_and_silver_graph(df) # 金银比走势图 #draw_gold_silver_ratio_graph(df) # 组合叠加图 #draw_gold_silver_and_ratio_graph(df) #添加表格输出功能 def print_comparison_table(df): """打印金银比对比表格""" # 创建摘要表格 summary = pd.DataFrame({ '指标': ['黄金均价(USD)', '白银均价(USD)', '金银比均值', '70分位值', '30分位值'], '数值': [ df['gold'].mean(), df['silver'].mean(), df['ratio'].mean(), df['ratio_70th'].iloc[0], df['ratio_30th'].iloc[0] ] }) # 格式化输出 print("\n" + "=" * 50) print(f"{ryear}-2025年金银市场对比分析") print("=" * 50) print(summary.to_string(index=False)) # 添加时间序列表格 print("\n近期价格趋势:") print(df[['date', 'gold', 'silver', 'ratio']].tail(10).to_string(index=False)) if __name__ == "__main__": # 自动下载数据 gold_url = "https://prices.lbma.org.uk/json/gold_pm.json?r=854633265" silver_url = "https://prices.lbma.org.uk/json/silver.json?r=65231548" download_data(gold_url, "gold.json") download_data(silver_url, "silver.json") # 处理数据 df = recombine_data_from_json() # 输出对比表格 print_comparison_table(df) # 新增表格输出 # 生成图表(可选) draw_gold_silver_and_ratio_graph(df) 此程序哪里有错误不能输出对比表和走势图之类图标,请帮忙修改成程序给出方案
10-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值