BOSS直聘招聘数据分析的第一步:用Python进行深度清洗

BOSS直聘招聘数据分析的第一步:用Python进行深度清洗

在数据分析和数据挖掘过程中,数据清洗是确保分析结果准确性的重要步骤。本文以从 BOSS直聘 爬取的"测试工程师"职位数据为例(数据爬取详见上篇文章),介绍如何使用Python对爬取的数据进行清洗,确保数据质量,以便后续分析和建模。


数据清洗的目标与方法

在数据分析前,清洗数据的主要目标是确保数据的一致性和完整性。常见的清洗任务包括:

  1. 处理缺失值:填充或删除缺失数据。
  2. 删除重复数据:去除重复行,确保数据唯一性。
  3. 标准化字段格式:统一字段值的格式(如薪资范围、年限要求等)。
  4. 检测并处理异常值:去除不合理的数据点,减少对分析结果的干扰。
  5. 清洗文本数据:清理职位描述等文本字段,为后续的文本分析做好准备。

数据清洗的代码实现

在数据清洗中,我们按照以下思路进行逐步实现,并为每个步骤提供代码示例和详细说明。


1. 数据读取与缺失值处理
1.1 数据读取

数据存储在 Excel 文件中,我们使用 pandas.read_excel() 读取数据。

python 复制代码
import pandas as pd

# 读取Excel数据
df = pd.read_excel('your_data.xlsx')  # 替换为实际文件路径
1.2 检查缺失值

通过 isnull().sum() 检查每列的缺失值数量,了解缺失数据的分布情况。

python 复制代码
# 检查缺失值分布
print("缺失值情况:")
print(df.isnull().sum())
1.3 填充或删除缺失值

根据字段的重要性和缺失值的性质,选择填充或删除策略。例如:

  • 薪资描述公司名称 等字段:填充为空字符串 ""
  • 年限要求学历要求 等字段:填充为"未指定"或其他默认值。
  • 缺失较多的数据行可以删除。
python 复制代码
# 填充缺失值
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() 检查数据是否存在重复行,删除多余数据以保证数据唯一性。

python 复制代码
# 检查重复数据
duplicates = df.duplicated().sum()
print(f"重复行数量:{duplicates}")

# 删除重复行
df.drop_duplicates(inplace=True)

3. 数据格式标准化

在招聘数据中,字段值的格式往往不一致。以下代码标准化了薪资、年限和学历字段。

3.1 薪资描述的标准化

将薪资字段(如 "10k-15k" 或 "年薪15万元")统一为数字表示,并以区间中位数表示。

python 复制代码
import re

def 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 10000
            return (min_salary + max_salary) * unit / 2
        # 匹配单一薪资(如 "年薪15万")
        match_annual = re.search(r'年薪(\d+)万', salary)
        if match_annual:
            return int(match_annual.group(1)) * 10000
    return None  # 返回None表示无法识别的薪资格式

# 应用薪资标准化函数
df['薪资描述'] = df['薪资描述'].apply(standardize_salary)
3.2 年限要求的标准化

统一年限格式(如 "1-3年" 转为平均年限,"3年以上" 转为单一值)。

python 复制代码
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 0
    return None

# 应用年限标准化函数
df['年限要求'] = df['年限要求'].apply(standardize_experience)
3.3 学历要求的标准化

将学历要求字段统一为规范格式,如 "本科"、"硕士" 等。

python 复制代码
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. 异常值检测

对数值字段(如薪资和年限)使用箱线图进行异常值检测,并删除不合理数据。

python 复制代码
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. 文本数据清洗

对岗位描述等文本字段,去除符号和空格,并进行分词处理。

python 复制代码
import jieba

def clean_text(text):
    """清洗文本数据"""
    text = re.sub(r'[^\w\s]', '', text)  # 去除符号
    return " ".join(jieba.cut(text))  # 分词处理

# 应用文本清洗函数
df['岗位要求'] = df['岗位要求'].apply(clean_text)

6. 结果检查与保存

清洗完成后,可以检查清洗后的数据并保存为新的 Excel 文件。

python 复制代码
# 查看清洗后的数据
print("清洗后的数据:")
print(df.head())

# 保存清洗后的数据
df.to_excel('cleaned_job_data.xlsx', index=False)

完整实现代码示例

python 复制代码
import pandas as pd
import re
import numpy as np


def 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)

        # 其他无效的薪资格式返回NaN
        return np.nan
    return np.nan


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  # 取年限区间的中位数

        # 匹配"经验不限"
        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))  # 返回最小年限

        # 无法匹配的返回NaN
        return np.nan
    return np.nan


def 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_num
    return np.nan


def 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)  # 保存清洗后的数据

清洗后的数据

总结

上述代码实现了以下功能:

  1. 缺失值处理:对缺失值进行了合理的填充或删除。
  2. 重复数据处理:删除了重复的行。
  3. 数据格式标准化:薪资、年限、学历等字段进行了标准化。
  4. 异常值检测:通过箱线图检测并删除了异常的薪资数据。
  5. 文本数据清洗:对岗位描述、任职要求进行了文本清洗和分词处理。

清洗后的数据更加规范和一致,为后续的数据分析和建模打下了坚实基础。完整代码已附上,欢迎试用并根据需求进行优化!

相关推荐
鳄鱼的眼药水19 分钟前
TT100K数据集, YOLO格式, COCO格式
人工智能·python·yolo·yolov5·yolov8
Tomorrow'sThinker20 分钟前
25年1月更新。Windows 上搭建 Python 开发环境:Python + PyCharm 安装全攻略(文中有安装包不用官网下载)
开发语言·python·pycharm
掐死你滴温柔4 小时前
SQLALchemy如何将SQL语句编译为特定数据库方言
数据结构·数据库·python·sql
西猫雷婶4 小时前
python学opencv|读取图像(二十三)使用cv2.putText()绘制文字
开发语言·python·opencv
陈序缘8 小时前
PyTorch快速入门
人工智能·pytorch·python·深度学习·算法·机器学习
编程梦想家(大学生版)8 小时前
使用Python和OpenCV进行视觉图像分割
开发语言·python·opencv
M姐实验室8 小时前
分类模型评估利器-混淆矩阵
人工智能·python·矩阵·分类
是Dream呀9 小时前
Python从0到100(八十一):神经网络-Fashion MNIST数据集取得最高的识别准确率
开发语言·python·神经网络
苏九黎9 小时前
Python爬虫入门
开发语言·爬虫·python
盲敲代码的阿豪9 小时前
利用python将图片转换为pdf格式的多种方法,实现批量转换,内置模板代码,全网最全,超详细!!!
python·pdf·图片转pdf