如何筛选DataFrame指定列值为英文的行并解决langdetect报错?
问题描述
我有一个包含27列的DataFrame,其中包含FonctionsStagiaire和ExigencesParticulieres两列,共13774行,内容均为英文或法文。我希望仅保留这两列值均为英文的行,删除列值为法文的整行。
使用langdetect库时遇到错误:
langdetect.lang_detect_exception.LangDetectException: No features in text.
试过Stack Overflow上的各种方案都没用,现在发现每行都会触发这个错误。另外还需要处理这两列里仅含NaN、数字、空格或标点这类没法检测语言的内容。
我优先想用langdetect,其他有效方案也可以接受,以下是我尝试的代码:
from langdetect import detect import pandas as pd import re import string def filter_nonenglish(df): list = ['FonctionsStagiaire', 'ExigencesParticulieres'] for col in list: #to check if values are only whitespaces or only numeric characters or only punctuation marks #something like this -> if (df[col].apply(lambda x: x.isnumeric()) == True) | (df[col].apply(lambda x: x.isspace()) == True) | (all(i in string.punctuation for i in df[col]) == True): return False else: #trying to use apply() to apply detect() to each <str> values of the columns and not to the entire pd.Series object new_df = df[(df[col].apply(detect).eq('en'))] return new_df #df['FonctionsStagiaire'] = df['FonctionsStagiaire'].apply(detect) #df['ExigencesParticulieres'] = df['ExigencesParticulieres'].apply(detect) #df = df[df['FonctionsStagiaire'] == 'en'] #df = df[df['ExigencesParticulieres'] == 'en'] #new_df = df[(df.FonctionsStagiaire.apply(detect).eq('en')) & (df.ExigencesParticulieres.apply(detect).eq('en'))] df = pd.read_csv('emplois_df_parsed.csv') df = df[df['FonctionsStagiaire'].notna() & df['ExigencesParticulieres'].notna()] #to remove empty values #to check whether all empty values are removed or not in the column 'FonctionsStagiaire' #df['FonctionsStagiaire'] = df['FonctionsStagiaire'].str.lower() #df = df[df['FonctionsStagiaire'].str.islower()] #to check whether all empty values are removed or not in the column 'ExigencesParticulieres' #df['ExigencesParticulieres'] = df['ExigencesParticulieres'].str.lower() #df = df[df['ExigencesParticulieres'].str.islower()] #to make sure that values of both the columns are of <str> datatype df['FonctionsStagiaire'] = pd.Series(df['FonctionsStagiaire'], dtype = "string") df['ExigencesParticulieres'] = pd.Series(df['ExigencesParticulieres'], dtype = "string") #bool(re.match('^(?=.*[a-zA-Z])', df.loc[:, 'FonctionsStagiaire'])) #bool(re.match('^(?=.*[a-zA-Z])', df.loc[:, 'ExigencesParticulieres'])) # df[df[column].map(lambda x: x.isascii())] df_new = filter_nonenglish(df) df_new.to_csv('emplois_df_filtered.csv', index= False)
解决方案
问题根源
langdetect.detect()无法处理仅含数字、空格、标点的字符串,这类内容没有语言特征,直接触发No features in text异常- 你的
filter_nonenglish函数逻辑错误:循环里直接return False会提前终止函数,而且没有同时筛选两列,最终只处理了最后一列
修复后的langdetect方案
先预处理过滤无效文本,再封装安全的检测函数,最后同时筛选两列均为英文的行:
from langdetect import detect, LangDetectException import pandas as pd import re def has_valid_text(text): """判断文本是否包含有效字母(排除仅数字、空格、标点的情况)""" if pd.isna(text): return False # 匹配至少一个大小写字母 return bool(re.search(r'[a-zA-Z]', str(text))) def safe_detect(text): """安全检测语言,捕获异常返回None""" if not has_valid_text(text): return None try: return detect(text) except LangDetectException: return None def filter_english_only(df): target_cols = ['FonctionsStagiaire', 'ExigencesParticulieres'] # 先过滤掉两列都无有效文本的行 df = df[df[target_cols].applymap(has_valid_text).any(axis=1)] # 为每列添加语言检测结果列 for col in target_cols: df[f'{col}_lang'] = df[col].apply(safe_detect) # 保留两列均检测为英文的行 result_df = df[(df['FonctionsStagiaire_lang'] == 'en') & (df['ExigencesParticulieres_lang'] == 'en')] # 移除临时语言列 result_df = result_df.drop(columns=[f'{col}_lang' for col in target_cols]) return result_df # 读取数据 df = pd.read_csv('emplois_df_parsed.csv') # 移除两列均为NaN的行 df = df[df['FonctionsStagiaire'].notna() & df['ExigencesParticulieres'].notna()] # 统一转换为字符串类型 df['FonctionsStagiaire'] = df['FonctionsStagiaire'].astype(str) df['ExigencesParticulieres'] = df['ExigencesParticulieres'].astype(str) # 执行筛选 df_new = filter_english_only(df) # 保存结果 df_new.to_csv('emplois_df_filtered.csv', index=False)
代码说明
has_valid_text:用正则快速过滤掉无有效字母的内容,避免无效检测safe_detect:封装检测函数,捕获异常防止崩溃,无效内容返回Nonefilter_english_only:先清理无效行,再检测语言,最后严格筛选两列都是英文的行
替代方案:使用langid库
如果langdetect还是不稳定,可以试试langid,它对短文本的兼容性更好:
先安装:
pip install langid
替换safe_detect函数:
import langid def safe_detect(text): if not has_valid_text(text): return None try: lang, _ = langid.classify(text) return lang except: return None
内容的提问来源于stack exchange,提问作者gmohor21
相关产品推荐
相关产品推荐

