Pandas数据清洗+数据分析小例,实战带图版

文摘   科技   2023-08-28 18:45   北京  


ISEE小语


小时候想拯救世界,长大后发现要先拯救自己。 

When I grew up,I realized that l had to save myself first.


——摘自:网络




回顾上篇



python中处理图像-调整尺寸、裁剪、旋转、添加滤镜和特效

ISEE小栈,公众号:ISEE小栈python中运用Pillow处理图像-调整尺寸、裁剪、旋转、添加滤镜和特效等,实践版


开始本篇


在用pandas做数据分析的时候,拿到的原始数据,会有些无效数据,为了更准确的进行数据分析和结果输出,我们通常需要先进行数据清洗,然后再进行后续的分析操作。



环境:

Pycharm

Python 3.9.16



安装:

pip install pandas==2.0.3

pip install matplotlib==3.7.1

pip install numpy==1.25.2


导入:

import pandas as pdimport matplotlib.pyplot as plt

(左右滑动查看完整代码)


设置全局字体:

# 设置全局字体plt.rcParams['font.family'] = 'Arial Unicode MS'

(左右滑动查看完整代码)


注:这个[设置全局字体]也需要补充到前篇,上次遗漏了



如果不设置全局字体的话,有可能在分析图上会出现乱码


首先,我们先准备分析的原数据data.csv,文章末尾附获取方式


读取CSV文件


通过pandas读取csv中的数据

df = pd.read_csv('data.csv')print(df)

(左右滑动查看完整代码)

结果:

原始数据559条

清洗数据


以上数据可以看到有些空值,还有重复的数据,那么就开始清洗吧


user_id列的数据


首先,我们先删除user_id重复的数据


使用drop_duplicates函数删除重复值

# 删除重复值,保留最后一项df.drop_duplicates(subset=['user_id'], inplace=True, keep='last')# 重新排序索引以使其连续df.reset_index(drop=True, inplace=True)print(df)

(左右滑动查看完整代码)

结果:

可以看出原来有559条数据,删除用户重复的数据,目前剩下531条数据


result列的数据


一、删除没有结果的值,即将result列为空的行删除


对整个DataFrame中的所有列进行检查并删除包含空值的行,可以使用df.dropna()

# 将result列为空的行删除df.dropna(subset=['result'], inplace=True)# 重新排序索引以使其连续df.reset_index(drop=True, inplace=True)print(df)

(左右滑动查看完整代码)

结果:

result列,已经没有显示NaN的数据了,目前剩下526条数据


二、将result列,float类型转为int类型

对于result只有两个值,1为拒绝,0为通过,改为整数,方便操作。

对整个DataFrame中的所有列进行类型转换,可以使用df.astype(int)

df['result'] = df['result'].astype(int)print(df)

(左右滑动查看完整代码)

结果:

result列,都显示为整数了



score列的数据


将score列的空值填充为数字0.00,定为默认值

用fillna函数实现空值的填充

df['score'].fillna(value=0.00, inplace=True)print(df)

(左右滑动查看完整代码)

结果:

score列,原来显示NaN的数据,都改为0.00



elapsed(ms)列的数据


一、将elapsed(ms)列的空值填充为数字1000.0,定为默认值


df['elapsed(ms)'].fillna(value=1000.0, inplace=True)print(df)

(左右滑动查看完整代码)

结果:

elapsed(ms)列,原来显示NaN的数据,都改为1000.0了


二、将elapsed(ms)列的毫秒,改为秒,并保留两位小数


将耗时换算成单位:秒,显示更加直接

df['elapsed(ms)'] = (df['elapsed(ms)'] / 1000).round(2)print(df)

(左右滑动查看完整代码)

结果:

elapsed(ms)列,单位秒,保留两位小数了


二、将列名elapsed(ms)修改为elapsed


df.rename(columns={'elapsed(ms)': 'elapsed'}, inplace=True)print(df)

(左右滑动查看完整代码)

结果:

原列名elapsed(ms)变为了elapsed


数据分析图

以上数据清洗完了,接下来根据实际需求,生成相应的分析图


统计结果生成饼状图


分别统计result通过和拒绝的数量,并以饼状图显示


# 统计数据results = dict()result_block = df['result'].value_counts(normalize=False)[1]results['result_block'] = result_blockresult_pass = df['result'].value_counts(normalize=False)[0]results['result_pass'] = result_pass# 生成饼状图df_results = pd.DataFrame.from_dict(results, orient='index', columns=['count'])plt.figure(figsize=(6, 6))df_results.plot.pie(y='count', autopct='%1.1f%%')plt.ylabel('')plt.title('结果分布比例')# 坐标轴plt.axis('equal')# 添加标签和图例plt.legend(['result_block:拒绝', 'result_pass:通过'], loc='best')plt.xlabel('2023年数据')plt.show()

(左右滑动查看完整代码)

结果:


统计分数线score数量


分别统计score大于0.5且result为0、score小于0.5且result为0和result为1拒绝的数据数量


count = dict()count_pass_up = df[(df['score'] > 0.5) & (df['result'] == 0)]['score'].shape[0]count_pass_down = df[(df['score'] <= 0.5) & (df['result'] == 0)]['score'].shape[0]count_block = df[df['result'] == 1]['score'].shape[0]count['0.5线上'] = count_pass_upcount['0.5线下'] = count_pass_downcount['拒绝'] = count_block# 创建DataFramedf_count = pd.DataFrame.from_dict(count, orient='index', columns=['Count'])# 设置柱子颜色colors = ['green', 'yellow', 'red']# 设置柱子宽度width = 0.4# 绘制柱状图ax = plt.bar(df_count.index, df_count['Count'], color=colors, width=width)# 添加数据标签for a in ax:    height = a.get_height()    plt.annotate(f'{height}', xy=(a.get_x() + a.get_width() / 2, height),                 xytext=(0, 3), textcoords='offset points',                 ha='center', va='bottom')# 设置标题和坐标轴标签plt.title('XXX分数线统计')plt.xlabel('指标')plt.ylabel('数量')# 设置图例handles = [plt.Rectangle((00), 11, color=color) for color in colors]plt.legend(handles, df_count.index, loc='best')# 显示图形plt.show()

(左右滑动查看完整代码)

结果:



统计耗时elapsed数据


分别统计elapsed在大于4秒、3-4秒之间、2-3秒之间,1-2秒之间,0-1秒之间,并且均为result为0的数据


elapsed = dict()elapsed_4 = len(df.query('elapsed >= 4 and result == 0'))elapsed_3_4 = len(df.query('elapsed >= 3 and elapsed < 4 and result == 0'))elapsed_2_3 = len(df.query('elapsed >= 2 and elapsed < 3 and result == 0'))elapsed_1_2 = len(df.query('elapsed >= 1 and elapsed < 2 and result == 0'))elapsed_0_1 = len(df.query('elapsed >= 0 and elapsed < 1 and result == 0'))elapsed['elapsed_0_1'] = elapsed_0_1elapsed['elapsed_1_2'] = elapsed_1_2elapsed['elapsed_2_3'] = elapsed_2_3elapsed['elapsed_3_4'] = elapsed_3_4elapsed['elapsed_4'] = elapsed_4# 创建DataFramedf_elapsed = pd.DataFrame.from_dict(elapsed, orient='index', columns=['Count'])# 设置柱子宽度width = 0.4fig, ax1 = plt.subplots()# 绘制柱状图ax = ax1.bar(df_elapsed.index, df_elapsed['Count'], color='blue', alpha=0.5, width=width)ax1.set_ylabel('Count')ax1.set_xlabel('Elapsed')# 添加数据标签for a in ax:    height = a.get_height()    plt.annotate(f'{height}', xy=(a.get_x() + a.get_width() / 2, height),                 xytext=(0, 3), textcoords='offset points',                 ha='center', va='bottom')# 绘制折线图ax2 = ax1.twinx()ax2.plot(df_elapsed.index, df_elapsed['Count'], color='red', marker='o', markersize=5)ax2.set_ylabel('Count')# 设置标题和坐标轴标签plt.title('XXX耗时量统计')plt.xlabel('指标')plt.ylabel('数量')# 显示图形plt.show()

(左右滑动查看完整代码)

结果:



总结

将以上分步归整:

--data.csv为测试数据

--data_analysis_tools.py为实际操作

有需求的朋友可自取哟

后台回复“pandas_analysis”即可获取~!


寄语:世间三美,明月,清风,眼前……

看到这儿的朋友帮点个“”和“在看”,谢谢支持~!

     

文章就分享到这儿,喜欢就点个吧!




推荐阅读  点击标题可跳转


ISEE小栈
没有花里胡哨,简单才是王道。
 最新文章