如何以更Pythonic的方式实现DataFrame多列的条件翻译?
问题描述
我写了一个接收DataFrame和布尔列表的函数,当布尔列表值为0时,对应位置的文本需要翻译成英文。但我觉得这个函数不够Pythonic,不符合最佳实践。
原函数代码:
def translate_text(df, mask): gs = goslate.Goslate() for sd, d, r, m in zip(df['short_description'], df['details'], df['resolution'], mask): if m == 0: # Perform translation sd = gs.translate(sd, 'en') d = gs.translate(d, 'en') r = gs.translate(r, 'en') return df
请问有没有更Pythonic的实现方式?求优化建议。
样例数据:
d = {'short_description': ['There is a problem with the laptop', 'Problemo y computer', 'There is a problem with the screen'], 'details': ['The laptop will not respond, just a black screen', 'Problemo y computer', 'The screen is just blinking'], 'resolution': ['Laptop has been replaced', 'La computadora ha sido reemplazada', 'Screen has been replaced']} df_sample = pd.DataFrame(data=d) mask = [1,0,1]
补充说明:上述示例为简化场景,假设所有列共用一个mask,实际场景中每个列都有独立的mask向量。
优化方案
首先明确原函数的核心问题:循环里的sd、d、r都是局部变量,修改后不会同步到原DataFrame,等于没有实际修改数据。以下分两种场景给出Pythonic的实现:
场景1:所有列共用同一个mask
利用pandas的布尔索引和批量操作替代显式循环,更符合pandas的设计逻辑:
import pandas as pd import goslate def translate_text(df, mask): gs = goslate.Goslate() # 将mask转为布尔索引,标记需要翻译的行 translate_rows = pd.Series(mask) == 0 # 对目标列的指定行批量翻译 target_cols = ['short_description', 'details', 'resolution'] df.loc[translate_rows, target_cols] = ( df.loc[translate_rows, target_cols] .applymap(lambda x: gs.translate(x, 'en')) ) return df # 测试调用 df_sample = translate_text(df_sample, mask) print(df_sample)
场景2:每个列有独立的mask
针对实际场景中各列mask独立的情况,按列单独处理:
def translate_text(df, column_masks): gs = goslate.Goslate() # column_masks为字典,key是列名,value是对应列的mask列表 for col, mask in column_masks.items(): translate_rows = pd.Series(mask) == 0 df.loc[translate_rows, col] = df.loc[translate_rows, col].apply(lambda x: gs.translate(x, 'en')) return df # 测试调用(模拟各列独立mask) column_masks = { 'short_description': [1,0,1], 'details': [1,0,0], 'resolution': [0,0,1] } df_sample = translate_text(df_sample, column_masks) print(df_sample)
额外优化建议
- 批量翻译提升效率:goslate支持批量翻译,将需要翻译的文本一次性传入,减少API调用次数:
# 以单列批量翻译为例 texts_to_translate = df.loc[translate_rows, col].tolist() translated_texts = gs.translate(texts_to_translate, 'en') df.loc[translate_rows, col] = translated_texts - 复用Goslate实例:如果函数会被多次调用,把
gs = goslate.Goslate()移到函数外部,避免重复初始化实例。 - 增加异常处理:翻译API可能因网络等问题失败,添加异常捕获避免程序崩溃:
def safe_translate(text, gs): try: return gs.translate(text, 'en') except Exception as e: print(f"翻译失败: {e}") return text # 失败时返回原文本 # 调用时替换为安全翻译函数 df.loc[translate_rows, col] = df.loc[translate_rows, col].apply(lambda x: safe_translate(x, gs))
内容的提问来源于stack exchange,提问作者Wolfy
相关产品推荐
相关产品推荐

