1.待分析的数据
是从智联招聘平台上手动爬取的python数据分析职位的相关信息,表的关键字分别为“薪金”、“学历”、“经验”。为后续数据分析做准备。数据部分截图,所示
智联招聘平台爬取‘python数据分析’职位,记录总共有500多条,其中包括一小部分重复发布的记录。考虑到数据量本身比较小,在此不对重复数据进行筛选。对关键字“学历”、“经验”,分别进行统计,发现其对应频率分别如下:
发现学历一栏“不限”和“中专”相对比较少,打印出内容,发现学历为“不限”的工资与学历“本科”比较接近,“中专”工资与“大专”比较接近,并无多大区别,因此修改dataframe中,将”不限”修改为“本科”,“中专”修改为“大专”。调用pandas的replace()函数
details.replace({'education': '不限'}, '本科', inplace=True) details.replace({'education': '中专'}, '大专', inplace=True)
details为原始数据表。注意,如果不想建立dataframe副本,可以设置inplace=True,直接修改原始dataframe.
同样道理,“无经验”,”1年以下“的工资和经验"不限”接近,同样可以合并。
details.replace({'experience': '无经验'}, '不限', inplace=True) # 可以这样做,因为不影响数据使用 details.replace({'experience': '1年以下'}, '不限', inplace=True)
“10年以上”,在本记录中只有一条数据,而且工资与其他差别很大,若将其并入“5-10”年,会直接拉高平均记录值,因此将其舍弃。
2.数据处理。
数据处理主要是分离将工资一栏分离得到,最低工资,最高工资,并分别将最低工资平均值,最高工资平均值,添加到学历,经验要求相同,工资为“面议”。为后续进行工资与学历,经验的关系做准备。
先把同等学历,经验要求的数据分开,代码如下:
# data_whole 是根据学历,经验筛选出的数据
# data_salary则是给出实际工资的数据
# data_negia是工资为“面议”的数据
data_whole = data[(data['experience'] == experience) & (data['education'] == education)] data_salary = data_whole[~ data_whole['salary'].isin(['面议'])] data_negia = data_whole[data_whole['salary'].isin(['面议'])]
这里在爬取数据时有一点需要注意的地方,我们在爬取数据时,往往需要用到python自带的一个小函数strip(),用于去掉字符串首尾的空格或者换行符,注意只能是首尾,不可以去除字符串中间空格。str.strip(). 原因是,我在抓取工资时,“面议“后面跟着一个空格,也就是我抓取的数据是”面议 ”,而不是"面议”。因此,我在判断isin(["面议“])
以下代码应根据具体爬取的数据分类讨论,我这里的数据,同一组条件,一定会出现给出工资的记录,但是不一定会出现工资为"面议”的记录,因此判断逻辑如下:
if len(data_salary) > 0: data_salary.reset_index(drop=True, inplace=True) low_salary, high_salary = split_salary(data_salary['salary'].apply(get_salary)) data_salary.insert(3, 'low_salary', low_salary) data_salary.insert(4, 'high_salary', high_salary) salary = data_salary.drop('salary', axis=1) # 如果面议表中有数据 if len(data_negia) > 0 : data_negia.reset_index(drop=True, inplace=True) data_negia.insert(3, 'low_salary', round(low_salary.mean())) data_negia.insert(4, 'high_salary', round(high_salary.mean())) salary = pd.concat([data_salary, data_negia], axis=0, ignore_index=True) salary.drop('salary', inplace=True, axis=1)
重要:data_salary.reset_index(drop=True, inplace=True)这句代码很重要,如果不重新对data_salary()索引进行排序,data_salary是从data_whole分离得到,索引并不会从0重新分布,而是保留data_whole的索引。如果不重新排列索引,在将最低工资,最高工资新插入data_salary,因为最低(高)工资的索引是从0开始,与data_salary索引不一致,因此会插入失败。个人理解,dataframe.insert()必须两者索引严格保持一致才可以插入列成功。
# split_salary()函数,是分别得到最低工资,最高工资
# get_salary()是获取具体的最低工资,最高工资金额。代码如下:
def get_salary(value): index_sep = value.find('-') index_end = value.find('元') return int(value[0:index_sep]), int(value[index_sep+1:index_end])
ef split_salary(tuple_list): try: if len(tuple_list) > 0: low_list = [] high_list = [] for tup in tuple_list: low = tup[0] high = tup[1] low_list.append(low) high_list.append(high) return pd.Series(low_list), pd.Series(high_list) except Exception: print('分离得到最低最高公资时出错')
3.完整代码
import pandas as pd def read_csv(filename): details = pd.read_csv(filename, sep=',', encoding='gb18030') details.replace({'experience': '无经验'}, '不限', inplace=True) # 可以这样做,因为不影响数据使用 details.replace({'experience': '1年以下'}, '不限', inplace=True) # 已经查看数据,并无区别 details.replace({'education': '不限'}, '本科', inplace=True) details.replace({'education': '中专'}, '大专', inplace=True) # 3-5年都有面议 salart_3to5 = pd.concat([handle_no_salary(details, '3-5年', '本科'), handle_no_salary(details, '3-5年', '硕士'), handle_no_salary(details, '3-5年', '大专')], axis=0,ignore_index=True) # 经验不限的无面议 salart_noexper = pd.concat([handle_no_salary(details, '不限', '本科'), handle_no_salary(details, '不限', '硕士'), handle_no_salary(details, '不限', '大专')], axis=0, ignore_index=True) # 5-10年,没有硕士 salary_5to10 = handle_no_salary(details, '5-10年', '本科') # 1-3年,都有面议 salary_1to3 = pd.concat([handle_no_salary(details, '1-3年', '本科'), handle_no_salary(details, '1-3年', '硕士'), handle_no_salary(details, '1-3年', '大专')], axis=0,ignore_index=True) salary_all = pd.concat([salart_3to5, salart_noexper, salary_5to10, salary_1to3], axis=0, ignore_index=True) print(len(salary_all)) # 把最低,最高公资填进去,并且把平均工资填进面议一栏 def get_salary(value): index_sep = value.find('-') index_end = value.find('元') return int(value[0:index_sep]), int(value[index_sep+1:index_end]) def split_salary(tuple_list): try: if len(tuple_list) > 0: low_list = [] high_list = [] for tup in tuple_list: low = tup[0] high = tup[1] low_list.append(low) high_list.append(high) return pd.Series(low_list), pd.Series(high_list) except Exception: print('分离得到最低最高公资时出错') def handle_no_salary(data, experience, education): data_whole = data[(data['experience'] == experience) & (data['education'] == education)] # 剔除面议的工资,填进去 data_salary = data_whole[~ data_whole['salary'].isin(['面议'])] data_negia = data_whole[data_whole['salary'].isin(['面议'])] if len(data_salary) > 0: data_salary.reset_index(drop=True, inplace=True) low_salary, high_salary = split_salary(data_salary['salary'].apply(get_salary)) data_salary.insert(3, 'low_salary', low_salary) data_salary.insert(4, 'high_salary', high_salary) salary = data_salary.drop('salary', axis=1) # 如果面议表中有数据 if len(data_negia) > 0 : data_negia.reset_index(drop=True, inplace=True) data_negia.insert(3, 'low_salary', round(low_salary.mean())) data_negia.insert(4, 'high_salary', round(high_salary.mean())) salary = pd.concat([data_salary, data_negia], axis=0, ignore_index=True) salary.drop('salary', inplace=True, axis=1) # axis = 0, 按照列对齐,ignore_index=True, 忽略两列表之前的索引,重新设置从0开始的索引 # 在某些函数,必须指定axis, 否则就会找不到一些索引而报错 print(experience, len(data_whole), len(data_salary), len(data_negia), len(salary)) return salary if __name__ == '__main__': read_csv("relation.csv")
4.我是数据分析小白,入手简单项目,围绕项目学习知识,是编程的最有效的途径。会遇到各种各样的问题,比如,因为事先不知道数据的分布特征,“本科”,“硕士”,“不限”,“中专”,”大专“,只理所当然考虑了”本科“,”硕士“这两种情况。因此,在进行数据处理前,最好利用value_counts()函数,看一下,每一列不同取值的大概分布。第一篇,内容估计有点乱,不过也算是往前迈了一大步。