You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中DataFrame差异基因高亮及Excel样式保存问题咨询

问题说明

我的DataFrame包含19列,以下仅保留关键列说明需求:

  • Gene_name:存储大肠杆菌的基因列表
  • Genes_in_same_transcription_unit:存储同启动子下的基因,条目以逗号+空格分隔(示例:pphA, sdsR)

需要找出Genes_in_same_transcription_unit中未出现在Gene_name里的基因,将其设置为红色字体高亮,以此快速判断操纵子受影响的位置(首基因、中间或末尾)。

目前代码能在Jupyter Notebook中生成带高亮效果的Highlighted_Genes列,但保存为Excel时样式丢失,现有代码如下:

# Convert Gene_name column to a set for quick lookup
gene_set = set(df['Gene_name'].dropna())  # Drop NaNs from Gene_name to avoid issues

# Function to highlight genes
def highlight_genes(row):
    genes_str = row['Genes_in_same_transcription_unit']
    
    # Handle NaN or missing values
    if pd.isna(genes_str):
        return None  # Keep NaNs as is
    
    genes_list = genes_str.split(', ')  # Split into list

    # Add asterisks to genes NOT in the Gene_name column
    highlighted_list = [f"*{gene}*" if gene not in gene_set else gene for gene in genes_list]
    
    return ', '.join(highlighted_list)  # Join back into string

# Apply function
df['Highlighted_Genes'] = df.apply(highlight_genes, axis=1)

# Function to highlight words inside asterisks
def highlight_genes(val):
    if not isinstance(val, str):  # Ensure it's a string
        return val  # Return as is (preserves NaN or other values)
    
    def replace_func(match):
        return f'<span style="color: red;">{match.group(1)}</span>'
    
    # Replace text between * * with a red-colored span tag
    highlighted_text = re.sub(r'\*(.*?)\*', replace_func, val)
    
    return highlighted_text

# Apply the function using Styler
df_styled = df.style.format({'Highlighted_Genes': lambda x: highlight_genes(x)})

# Display in Jupyter Notebook
df_styled

df_styled.to_excel('highlighted_genes.xlsx')
问题原因

Pandas的Styler.to_excel()不支持HTML格式的样式渲染,只会把<span>这类标签当作普通文本写入Excel,导致样式丢失。要在Excel中实现单元格内部分文本的高亮,需要直接操作Excel的富文本格式,而非依赖HTML。

解决方案

使用openpyxl库直接生成带富文本格式的Excel文件,以下是两种实现方式:

方式1:基于预处理标记列生成高亮

先标记需要高亮的基因,再写入Excel时设置对应字体颜色:

import pandas as pd
import openpyxl
from openpyxl.styles import Font
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.cell.text import InlinePatternedText, TextBlock

# 初始化基因集合用于快速查询
gene_set = set(df['Gene_name'].dropna())

# 生成标记列,存储(基因名, 是否需要高亮)的列表
def mark_target_genes(row):
    genes_str = row['Genes_in_same_transcription_unit']
    if pd.isna(genes_str):
        return None
    genes_list = genes_str.split(', ')
    return [(gene, gene not in gene_set) for gene in genes_list]

df['Highlighted_Genes'] = df.apply(mark_target_genes, axis=1)

# 创建Excel工作簿
wb = openpyxl.Workbook()
ws = wb.active

# 写入表头和数据行
for r_idx, row in enumerate(dataframe_to_rows(df, index=False, header=True), 1):
    for c_idx, val in enumerate(row, 1):
        cell = ws.cell(row=r_idx, column=c_idx, value=val)
        # 跳过表头,只处理Highlighted_Genes列
        if r_idx == 1 or c_idx != df.columns.get_loc('Highlighted_Genes') + 1:
            continue
        if val is None:
            continue
        # 清空单元格默认值,准备写入富文本
        cell.value = None
        parts = []
        for i, (gene, need_highlight) in enumerate(val):
            if i > 0:
                # 添加分隔符
                parts.append(InlinePatternedText(text=', ', font=Font()))
            # 设置字体颜色:红色高亮/默认黑色
            font = Font(color="FF0000") if need_highlight else Font()
            parts.append(InlinePatternedText(text=gene, font=font))
        cell._value = TextBlock(parts=parts)

# 保存文件
wb.save('highlighted_genes.xlsx')

方式2:直接处理原始列(无需额外标记列)

直接读取原始列数据,写入Excel时动态判断并设置高亮:

import pandas as pd
import openpyxl
from openpyxl.styles import Font
from openpyxl.cell.text import InlinePatternedText, TextBlock

# 初始化基因集合
gene_set = set(df['Gene_name'].dropna())

# 创建Excel工作簿
wb = openpyxl.Workbook()
ws = wb.active

# 写入表头
ws.append(df.columns.tolist())

# 写入数据行并设置高亮
for _, row in df.iterrows():
    ws.append(row.tolist())
    current_row = ws.max_row
    # 获取目标列的单元格索引(根据你的列位置调整)
    target_col_idx = df.columns.get_loc('Genes_in_same_transcription_unit') + 1
    cell = ws.cell(row=current_row, column=target_col_idx)
    genes_str = cell.value
    
    if pd.isna(genes_str):
        continue
    # 清空单元格默认值
    cell.value = None
    parts = []
    genes_list = genes_str.split(', ')
    for i, gene in enumerate(genes_list):
        if i > 0:
            parts.append(InlinePatternedText(text=', ', font=Font()))
        # 判断是否需要高亮
        font = Font(color="FF0000") if gene not in gene_set else Font()
        parts.append(InlinePatternedText(text=gene, font=font))
    cell._value = TextBlock(parts=parts)

# 保存文件
wb.save('highlighted_genes.xlsx')

运行上述代码后,Excel文件中目标列内不在Gene_name中的基因会显示为红色,样式完全保留。

内容的提问来源于stack exchange,提问作者Melissa Arroyo-Mendoza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 14:39:57