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 pd
import 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_block
result_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_up
count['0.5线下'] = count_pass_down
count['拒绝'] = count_block
# 创建DataFrame
df_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((0, 0), 1, 1, 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_1
elapsed['elapsed_1_2'] = elapsed_1_2
elapsed['elapsed_2_3'] = elapsed_2_3
elapsed['elapsed_3_4'] = elapsed_3_4
elapsed['elapsed_4'] = elapsed_4
# 创建DataFrame
df_elapsed = pd.DataFrame.from_dict(elapsed, orient='index', columns=['Count'])
# 设置柱子宽度
width = 0.4
fig, 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”即可获取~!
寄语:世间三美,明月,清风,眼前……
看到这儿的朋友帮点个“赞”和“在看”,谢谢支持~!
文章就分享到这儿,喜欢就点个赞吧!