BOSS直聘招聘数据分析的第一步:用Python进行深度清洗
在数据分析和数据挖掘过程中,数据清洗是确保分析结果准确性的重要步骤。本文以从 BOSS直聘 爬取的“测试工程师”职位数据为例(数据爬取详见上篇文章),介绍如何使用Python对爬取的数据进行清洗,确保数据质量,以便后续分析和建模。
数据清洗的目标与方法
在数据分析前,清洗数据的主要目标是确保数据的一致性和完整性。常见的清洗任务包括:
- 处理缺失值:填充或删除缺失数据。
- 删除重复数据:去除重复行,确保数据唯一性。
- 标准化字段格式:统一字段值的格式(如薪资范围、年限要求等)。
- 检测并处理异常值:去除不合理的数据点,减少对分析结果的干扰。
- 清洗文本数据:清理职位描述等文本字段,为后续的文本分析做好准备。
数据清洗的代码实现
在数据清洗中,我们按照以下思路进行逐步实现,并为每个步骤提供代码示例和详细说明。
1. 数据读取与缺失值处理
1.1 数据读取
数据存储在 Excel 文件中,我们使用 pandas.read_excel()
读取数据。
import pandas as pd# 读取Excel数据
df = pd.read_excel('your_data.xlsx') # 替换为实际文件路径
1.2 检查缺失值
通过 isnull().sum()
检查每列的缺失值数量,了解缺失数据的分布情况。
# 检查缺失值分布
print("缺失值情况:")
print(df.isnull().sum())
1.3 填充或删除缺失值
根据字段的重要性和缺失值的性质,选择填充或删除策略。例如:
- 薪资描述、公司名称 等字段:填充为空字符串
""
。 - 年限要求、学历要求 等字段:填充为“未指定”或其他默认值。
- 缺失较多的数据行可以删除。
# 填充缺失值
df['薪资描述'].fillna("", inplace=True)
df['公司名称'].fillna("", inplace=True)
df['年限要求'].fillna("未指定", inplace=True)
df['学历要求'].fillna("未指定", inplace=True)# 删除超过50%字段缺失的行
df.dropna(thresh=len(df.columns)*0.5, axis=0, inplace=True)
2. 重复数据处理
通过 duplicated()
检查数据是否存在重复行,删除多余数据以保证数据唯一性。
# 检查重复数据
duplicates = df.duplicated().sum()
print(f"重复行数量:{duplicates}")# 删除重复行
df.drop_duplicates(inplace=True)
3. 数据格式标准化
在招聘数据中,字段值的格式往往不一致。以下代码标准化了薪资、年限和学历字段。
3.1 薪资描述的标准化
将薪资字段(如 “10k-15k” 或 “年薪15万元”)统一为数字表示,并以区间中位数表示。
import redef standardize_salary(salary):"""标准化薪资描述为数值"""if isinstance(salary, str):salary = salary.strip()# 匹配薪资范围(如 "10k-15k")match = re.match(r'(\d+)(k|万)?-(\d+)(k|万)?', salary)if match:min_salary = int(match.group(1))max_salary = int(match.group(3))unit = 1000 if match.group(2) in ['k', 'K'] else 10000return (min_salary + max_salary) * unit / 2# 匹配单一薪资(如 "年薪15万")match_annual = re.search(r'年薪(\d+)万', salary)if match_annual:return int(match_annual.group(1)) * 10000return None # 返回None表示无法识别的薪资格式# 应用薪资标准化函数
df['薪资描述'] = df['薪资描述'].apply(standardize_salary)
3.2 年限要求的标准化
统一年限格式(如 “1-3年” 转为平均年限,“3年以上” 转为单一值)。
def standardize_experience(experience):"""标准化年限要求为数值"""if isinstance(experience, str):experience = experience.strip()# 匹配年限范围(如 "1-3年")match = re.match(r'(\d+)-(\d+)年', experience)if match:return (int(match.group(1)) + int(match.group(2))) / 2# 匹配单一年限(如 "3年以上")elif '年以上' in experience:return int(experience.split('年')[0])# 无经验或不限elif '不限' in experience or '应届生' in experience:return 0return None# 应用年限标准化函数
df['年限要求'] = df['年限要求'].apply(standardize_experience)
3.3 学历要求的标准化
将学历要求字段统一为规范格式,如 “本科”、“硕士” 等。
def standardize_education(education):"""标准化学历要求"""if isinstance(education, str):if '本科' in education:return '本科'elif '硕士' in education:return '硕士'elif '博士' in education:return '博士'elif '大专' in education:return '大专'return '不限'# 应用学历标准化函数
df['学历要求'] = df['学历要求'].apply(standardize_education)
4. 异常值检测
对数值字段(如薪资和年限)使用箱线图进行异常值检测,并删除不合理数据。
import matplotlib.pyplot as plt# 绘制箱线图
plt.figure(figsize=(10, 6))
df['薪资描述'].plot(kind='box')
plt.title("薪资分布箱线图")
plt.show()# 删除异常值(薪资低于3000或高于30000的职位)
df = df[(df['薪资描述'] >= 3000) & (df['薪资描述'] <= 30000)]
5. 文本数据清洗
对岗位描述等文本字段,去除符号和空格,并进行分词处理。
import jiebadef clean_text(text):"""清洗文本数据"""text = re.sub(r'[^\w\s]', '', text) # 去除符号return " ".join(jieba.cut(text)) # 分词处理# 应用文本清洗函数
df['岗位要求'] = df['岗位要求'].apply(clean_text)
6. 结果检查与保存
清洗完成后,可以检查清洗后的数据并保存为新的 Excel 文件。
# 查看清洗后的数据
print("清洗后的数据:")
print(df.head())# 保存清洗后的数据
df.to_excel('cleaned_job_data.xlsx', index=False)
完整实现代码示例
import pandas as pd
import re
import numpy as npdef standardize_salary(salary):"""标准化薪资数据,转换为数值形式"""if isinstance(salary, str):salary = salary.strip()# 匹配薪资范围,如"6-9K"match = re.match(r'(\d+)-(\d+)(K|k|万)?', salary)if match:min_salary = int(match.group(1)) * (1000 if match.group(3).lower() == 'k' else 10000)max_salary = int(match.group(2)) * (1000 if match.group(3).lower() == 'k' else 10000)return (min_salary + max_salary) / 2 # 取区间的平均值# 匹配年薪格式,如"年薪15万·14薪"match_annual = re.match(r'(\d+)-(\d+)(K|k)?[\s·]*(\d+)薪', salary)if match_annual:base_salary = int(match_annual.group(1)) * (1000 if match_annual.group(3).lower() == 'k' else 10000)extra_salary = int(match_annual.group(2)) * (1000 if match_annual.group(3).lower() == 'k' else 10000)extra_months = int(match_annual.group(4))return (base_salary + extra_salary) * extra_months / 12 # 按年薪计算# 处理其他情况,如"10K"或"15万"match_single = re.match(r'(\d+)(K|k|万)?', salary)if match_single:return int(match_single.group(1)) * (1000 if match_single.group(2).lower() == 'k' else 10000)# 其他无效的薪资格式返回NaNreturn np.nanreturn np.nandef standardize_experience(experience):"""标准化年限数据,转换为数值"""if isinstance(experience, str):experience = experience.strip()# 匹配年限范围,如“1-3年”match = re.match(r'(\d+)-(\d+)年', experience)if match:return (int(match.group(1)) + int(match.group(2))) / 2 # 取年限区间的中位数# 匹配“经验不限”if '经验不限' in experience:return 0 # 经验不限时认为是0年# 匹配“应届生”if '应届生' in experience:return 0 # 应届生视为0年经验# 匹配“大于5年”等描述match_greater_than = re.match(r'(\d+)年.*以上', experience)if match_greater_than:return int(match_greater_than.group(1)) # 返回最小年限# 无法匹配的返回NaNreturn np.nanreturn np.nandef standardize_education(education):"""标准化学历要求"""if isinstance(education, str):education = education.strip().lower()# 处理本科以上,本科及其他if '本科' in education:return '本科'elif '硕士' in education:return '硕士'elif '博士' in education:return '博士'elif '大专' in education:return '大专'else:return '不限'return '不限'def standardize_company_size(size):"""标准化公司规模,清理异常值"""if isinstance(size, str):size = size.strip()# 匹配数字match = re.match(r'(\d+)', size)if match:size_num = int(match.group(1))if size_num < 10 or size_num > 100000:return np.nan # 异常的公司规模return size_numreturn np.nandef clean_job_data(df):"""对招聘数据进行清洗"""# 薪资描述清洗df['薪资描述'] = df['薪资描述'].apply(standardize_salary)df = df[(df['薪资描述'] >= 3000) & (df['薪资描述'] <= 30000)] # 薪资限制# 年限要求清洗df['年限要求'] = df['年限要求'].apply(standardize_experience)df = df[(df['年限要求'] >= 0) & (df['年限要求'] <= 40)] # 年限限制# 学历要求清洗df['学历要求'] = df['学历要求'].apply(standardize_education)# 公司规模清洗df['公司规模'] = df['公司规模'].apply(standardize_company_size)# 返回清洗后的数据return df# 使用示例
if __name__ == "__main__":df = pd.read_excel('jobs.xlsx') # 假设你已经爬取的数据存储在此文件中cleaned_df = clean_job_data(df)cleaned_df.to_excel('cleaned_job_data.xlsx', index=False) # 保存清洗后的数据
清洗后的数据
总结
上述代码实现了以下功能:
- 缺失值处理:对缺失值进行了合理的填充或删除。
- 重复数据处理:删除了重复的行。
- 数据格式标准化:薪资、年限、学历等字段进行了标准化。
- 异常值检测:通过箱线图检测并删除了异常的薪资数据。
- 文本数据清洗:对岗位描述、任职要求进行了文本清洗和分词处理。
清洗后的数据更加规范和一致,为后续的数据分析和建模打下了坚实基础。完整代码已附上,欢迎试用并根据需求进行优化!