配色
可以在平时阅读时保存一些好看图像的配色/架构,例如


或者可以直接参考 配色网站,不过比较麻烦的是得自己去找颜色
绘图
AI 辅助
用提示词生成绘图脚本,例如仙人掌图(cactus)的代码如下:
import pandas as pd
import matplotlib.pyplot as plt
import os
import numpy as np
# --- 配置参数 ---
# CSV文件所在的目录
# EXPR_NAME = "MagicSquare-LS"
EXPR_NAME = "SAT22"
DATA_DIR = f"./data/{EXPR_NAME}"
# 预设的超时时间限制(秒)。所有超过此时间的,都视为超时。
TIMEOUT = 5000
# 输出图片的文件名
OUTPUT_FILENAME = f"fig/{EXPR_NAME}_cactus_plot.png"
BACKGOUND = "gray"
# , #, #, #
# 算法名称及其对应的绘图样式(用于确保学术严谨性,避免花哨)
# 使用不同的标记、线条样式和有限的颜色
ALGORITHM_STYLES = {
"CardSAT-INC": {
"label": "CardSAT-INC",
"color": "#85C3DC",
"marker": "o",
"linestyle": "-",
},
"YalSAT": {
"label": "YalSAT",
"color": "#8DAFAB",
"marker": "^",
"linestyle": "--",
},
"CCAnr": {
"label": "CCAnr",
"color": "#E2C098",
"marker": "s",
"linestyle": ":",
},
"NuPBO": {
"label": "NuPBO",
"color": "#DAC6CF",
"marker": "x",
"linestyle": "-",
},
}
def load_and_prepare_data(data_dir, timeout, styles):
"""
加载所有 CSV 文件,处理数据,并为仙人掌图准备排序后的求解时间。
"""
algorithm_data = {}
# 遍历指定目录下的所有文件
for filename in os.listdir(data_dir):
if filename.endswith(".csv"):
# 从文件名中提取算法名称(假设文件名格式为 'AlgorithmName.csv')
algorithm_name = filename.replace("-results.csv", "")
if algorithm_name not in styles:
print(
f"Warning: Skipping file {filename}. No style defined for '{algorithm_name}'."
)
continue
filepath = os.path.join(data_dir, filename)
try:
# 1. 读取 CSV 文件
df = pd.read_csv(filepath)
# 2. 数据清洗与处理:将超时或未解决的实例时间设为 TIMEOUT
# 假设 'time' 列记录了时间,'status' 列记录了状态
# a) 处理超时时间
df["processed_time"] = np.where(
df["time"] >= timeout, timeout, df["time"]
)
# b) 进一步处理未解决的状态(如果状态不是 'solved',也视为超时)
# 您可能需要根据您的实际状态标签修改这里的条件
if "result" in df.columns:
df["processed_time"] = np.where(
df["result"] == "TIMEOUT",
timeout,
df["processed_time"],
)
# 3. 核心步骤:按时间升序排序
# 仙人掌图的 X 轴是解决的问题数量,Y 轴是求解时间
solved_df = df[
(df["time"] <= timeout) & (df["result"] != "TIMEOUT")
].copy()
sorted_times = solved_df["time"].sort_values().tolist()
# 4. Y轴数据准备:累积求解时间
# 仙人掌图的 Y 轴是 *求解时间*,X 轴是 *解决的问题数*
# 注意:这里我们实际使用的Y轴是排序后的时间本身,而不是累积时间,
# 因为仙人掌图是 (已解决问题数, 求解该问题所需时间) 的曲线
algorithm_data[algorithm_name] = sorted_times
except Exception as e:
print(f"Error processing file {filename}: {e}")
continue
return algorithm_data
def plot_cactus_plot(data, styles, timeout, output_filename):
"""
绘制仙人掌图。
"""
plt.style.use("default") # 使用默认或尝试 'seaborn-v0_8-whitegrid' 或 ''
fig, ax = plt.subplots(figsize=(10, 6))
fig.patch.set_facecolor("#f5f5f5")
# ax.set_facecolor("#e8e8e8")
all_num_problems = []
# 绘制每个算法的曲线
for algo_name, times in data.items():
style = styles[algo_name]
# X 轴数据:已解决问题的数量(从 1 开始)
# 如果算法解决了 N 个问题,那么 X 轴的坐标就是 1, 2, 3, ..., N
num_solved = len(times)
x_data = np.arange(1, num_solved + 1)
y_data = np.array(times)
# 记录所有算法的总问题数,用于确定 X 轴范围
all_num_problems.append(num_solved)
# 绘制曲线,使用预定义的学术样式
ax.plot(
x_data,
y_data,
label=style["label"],
color=style["color"],
marker=style.get("marker", None),
linestyle=style.get("linestyle", "-"),
linewidth=2,
markevery=max(1, num_solved // 15), # 每隔一定数量的点才显示标记,避免拥挤
markersize=5,
)
# --- 图表美化设置 (学术严谨性) ---
# 设置 X 轴(已解决的问题实例数量)
max_problems = max(all_num_problems) if all_num_problems else 1
ax.set_xlabel("Number of Solved Instances", fontsize=12)
ax.set_xlim(0, max_problems * 1.05)
# 确保 X 轴刻度是整数
ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
# 设置 Y 轴(求解时间)
ax.set_ylabel("CPU Time (seconds)", fontsize=12)
# 设置 Y 轴的上限为 TIMEOUT,并使用对数刻度以清晰显示小时间差异
ax.set_ylim(bottom=0.01, top=timeout * 1.1)
ax.set_yscale("log")
# --- 关键修改:超时线不设置 label,因此不会进入图例 ---
ax.axhline(y=timeout, color="red", linestyle="--", linewidth=1, zorder=0)
# 可以在图内添加文本标记超时线,以提高清晰度
# ax.text(
# ax.get_xlim()[1] * 0.98,
# timeout * 1.05,
# f"Timeout ({timeout}s)",
# color="red",
# fontsize=10,
# ha="right",
# va="center",
# )
# 添加网格线,帮助阅读数据点
# ax.grid(True, which="both", linestyle="-", linewidth=0.5, alpha=0.7)
# 添加图例
# 使用 loc='best' 或指定位置,frameon=True 增强可读性
ax.legend(loc="lower right", fontsize=10, frameon=True, shadow=False)
# 标题(可选,通常在论文中放在图下方)
# plt.title('Cactus Plot: Comparison of Algorithm Performance', fontsize=14)
# 调整布局,保存图像
plt.tight_layout()
plt.savefig(output_filename, dpi=300)
plt.close(fig)
print(f"Cactus Plot successfully saved to {output_filename}")
# --- 主执行流程 ---
# 1. 检查数据目录是否存在
if not os.path.exists(DATA_DIR):
print(f"Error: Data directory '{DATA_DIR}' not found.")
print("Please create the directory and place your CSV files inside.")
else:
# 2. 加载和准备数据
performance_data = load_and_prepare_data(DATA_DIR, TIMEOUT, ALGORITHM_STYLES)
if performance_data:
# 3. 绘制仙人掌图
plot_cactus_plot(performance_data, ALGORITHM_STYLES, TIMEOUT, OUTPUT_FILENAME)
else:
print(
"No valid data loaded for plotting. Check your CSV files and ALGORITHM_STYLES."
)提示词需要传递的信息主要是:
- 配色,字体
- csv 文件格式
- 以及你自己的一些想法
AI 生成
用 nano banana 来生成,具体流程为:
-
用提示词在简单模型上生成绘图提示词,例如在
deepseek上用以下提示词:你是一名经验丰富的科研绘图设计师,请仔细阅读我提供的文献信息,充分理解研究内容,并结合我提供的参考图(模仿该图的配色、设计风格等),生成可用于科研发表的配图的英文提示词。
-
用生成的提示词,复制粘贴到
Nano Banana中生成
Matplotlib 的 Marker

或者可以考虑使用 unicode 字符编码,例如 "$\u266B$"(支持 STIX Font Math 中的字符)
Tip
如果需要空心的话,注明
color=""以及edgecolors="#hex"即可(边框有颜色,中间无颜色)