综合使用pandasnumpymatplotlibseaborn库做数据分析挖掘可视化项目
综合使用pandas、numpy、matplotlib、seaborn库做数据分析、挖掘、可视化项目
1 . 结构化数据挖掘
1 . 1 依赖库导入和数据读取
导入必要的依赖库,读取 csv 格式数据集转化为 Dataframe 格式,命名为 data,使用 pandas 必要接口,并打印数据集的前五个样本。
# 数据导入和观察
import pandas as pd
data = pd.read_csv('cleaned_all_phones.csv')
data.head()
说明:
import pandas as pd
导入Pandas库,并将其简称为
pd
。Pandas是一个强大的数据分析和处理库,广泛用于数据清洗、转换、分析和可视化。
data = pd.read_csv(‘cleaned_all_phones.csv’)
使用Pandas的
read_csv()
函数加载一个名为
cleaned_all_phones.csv
的CSV文件。这个文件可能包含手机相关的数据,例如品牌、价格、性能指标等。
read_csv()
函数会将CSV文件读取为一个
DataFrame
对象,这是Pandas中用于存储表格数据的主要数据结构。
data.head()
调用
head()
方法显示
DataFrame
的前五行数据。这是数据探索的常用操作,用于快速查看数据的结构和内容。
1.2 各品牌机型及售价统计
统计各品牌发布的机型数量,并绘制机型数量关于品牌的柱形图,统计个品牌发布的机型的价格均值,并绘制机型价格均值关于品牌的柱形图。
# 可视化数据分布
import matplotlib.pyplot as plt
import seaborn as sns
fig, ax = plt.subplots(1,2,figsize=(20,6))
brand_counts = data['brand'].value_counts()
sns.barplot(x=brand_counts.index, y=brand_counts.values, ax=ax[0],color='red')
ax[0].set_xlabel('Brand')
ax[0].set_ylabel('Count')
ax[0].set_title('Brand Distribution')
ax[0].tick_params(axis='x',rotation=90)
brand_price_mean = data.groupby('brand')['price(USD)'].mean()
sns.barplot(x=brand_price_mean.index, y=brand_price_mean.values, ax=ax[1],color='red')
ax[1].set_xlabel('Brand')
ax[1].set_ylabel('Averge Price')
ax[1].set_title('Brand X Price Distribution')
ax[1].tick_params(axis='x',rotation=90)
plt.tight_layout()
plt.show()
说明:
seaborn
:基于
matplotlib
的高级绘图库,提供了更简洁的API和更美观的默认样式,特别适合用于统计图表的绘制。
fig,ax = plt.subplots(1,2,figsize=(20,6))
使用
plt.subplots()
创建一个包含1行2列的图形布局,总尺寸为20×6英寸。
fig
表示整个图形对象,
ax
是一个包含两个子图的数组,分别用于绘制不同的图表。
brand_counts = data['brand'].values_counts()
brand_counts_mean = data.groupby('brand')['price(USD)'].mean()
brand_counts
:使用
value_counts()
方法统计
brand
列中每个品牌出现的次数。
brand_price_mean
:使用
groupby()
方法按品牌分组,并计算每个品牌的平均价格。
sns.barplot(x=brand_counts.index,y=brand_counts.values,ax=ax[0],color='red')
ax[0].set_xlabel('Brand')
ax[0].set_ylabel('Count')
ax[0].set_title('Brand Distribution')
ax[0].tick_params(axis='x',rotation=90)
使用
seaborn
的
barplot()
方法绘制柱状图
:
x=brand_counts.index
:品牌名称作为横轴
y=brand_counts.values
:品牌出现的次数作为纵轴
ax=ax[0]
:指定将图表绘制在第一个子图上
color=‘red’
:将柱子的颜色设置为红色
使用
ax[0].set_xlabel()
、
ax[0].set_ylabel()
和
ax[0].set_title()
设置横轴标签、纵轴标签和标题。
使用
ax[0].tick_params(axis=‘x’, rotation=90)
将横轴标签旋转90度,避免标签重叠。
sns.barplot(x=brand_price_mean.index,y=brand_price_mean.values,ax[1],color='red')
ax[1].set_xlabel('Brand')
ax[1].set_ylabel('Average Price')
ax[1].set_title('Brand X Price Distribution')
ax[1].tick_params(axis='x',rotation=90)
绘制第二个
子图
,
参数
同上
库的应用拓展
Matplotlib的更多功能
自定义图表样式:
plt.style.use('ggplot') # 使用ggplot风格
添加网格线:
ax[0].grid(axis='y', linestyle='--', alpha=0.7)
添加注释:
ax[0].annotate('Highest Count', xy=('Brand A', 100), xytext=(10, 10),
arrowprops=dict(facecolor='black', shrink=0.05))
Seaborn的更多功能
绘制箱线图:
sns.boxplot(x='brand', y='price(USD)', data=data)
绘制热力图:
sns.heatmap(data.corr(), annot=True, cmap='coolwarm')
绘制散点图矩阵:
sns.pairplot(data, hue='brand')
结合Pandas进行更复杂的数据分析
分组统计:
brand_stats = data.groupby('brand').agg({'price(USD)': ['mean', 'median', 'std']})
条件筛选与可视化:
high_price_brands = data[data['price(USD)'] > 1000]
sns.scatterplot(x='brand', y='price(USD)', data=high_price_brands)
1.3 视频录制规格与价格关联性分析
以 10 种不同的视频录制规格作为特征,分别绘制价格有关这 10 种特征的 10 张箱线图,将 10 张箱线图打印在一个同画布上。
# 分析某个(某些)特征与标签(1:1)的关系可以用到箱线图sns.boxplot()
video_feature = [col for col in data.columns if col.startswith('video')]
plt.subplots(4,3,figsize=(30,30))
for idx,feature in enumerate(video_feature,start=1):
plt.subplot(4,3,idx)
sns.boxplot(x=feature, y='price(USD)', data=data, hue=feature, palette={False:'red',True:'blue'}) #
plt.xlabel('feature')
plt.ylabel('price(USD)')
plt.title('price box plot')
说明
:
video_feature = [col for col in data.columns if col.startswith('vedio_')]
使用列表推导式从
data
的列名中筛选出以“video”开头的特征列
这些特征可能与视频功能相关,例如
video_resolution
(视频分辨率)、
video_fps
(视频帧率)等
for idx,feature in enumerate(vedio_feature,start=1):
plt.subplot(4,3,idx)
sns.boxplot(x=feature,y='price(USD)',data=data,hue=feature,palette={False:'red',True:'blue'})
plt.xlabel('feature')
plt.ylabel('price(USD)')
plt.title('price box plot')
enumerate(video_feature, start=1)
:遍历
video_feature
列表,并为每个特征分配一个索引(从1开始)。
plt.subplot(4, 3, idx)
:根据索引将每个箱线图绘制在对应的子图位置。
sns.boxplot()
:使用Seaborn的
boxplot()
方法绘制箱线图
x=feature
:将特征列作为横轴。
y=‘price(USD)’
:将价格作为纵轴。
data=data
:指定数据源。
hue=feature
:根据特征的值
对箱线图进行分组
(假设特征是布尔类型,如
True
或
False
)。
palette={False: ‘red’, True: ‘blue’}
:
为分组设置颜色
,
False
为红色,
True
为蓝色。
plt.xlabel(‘feature’)
、 plt.ylabel(‘price(USD)’)
、 plt.title(‘price box plot’)
:设置横轴标签、纵轴标签和标题
补充:
箱线图的作用
为什么可以用箱线图分析特征与标签的关系?
箱线图是一种用于展示一组数据的五数概括(最小值、第一四分位数、中位数、第三四分位数和最大值)的图表。
通过箱体和须线直观地展示
了数据的分布情况,包括中位数、分布范围、异常值等。
分析特征与标签的关系
:
在机器学习和数据分析中,箱线图可以用来分析特征与标签之间的关系,尤其是当特征是分类变量(如布尔值、类别标签)时:
分布差异:通过比较不同特征值对应的标签分布,可以直观地看出特征值对标签的影响。例如,某些特征值可能导致标签值的分布更集中或更分散。
异常值检测:箱线图可以清晰地展示异常值,帮助分析特征与异常标签值之间的关系。
适用场景:
特征是分类变量:当特征是布尔值(如True/False)或类别标签
时,箱线图可以很好地展示不同类别对应的标签分布差异。例如,video_feature可能是布尔值(如是否支持高清视频录制),箱线图可以直观地展示支持与不支持高清视频的手机价格分布差异。
标签是连续变量
:箱线图适用于分析连续标签(如价格)的分布情况。通过箱线图,可以快速判断特征对标签分布的影响。
限制
:
特征是连续变量时的局限性
:如果特征是连续变量,箱线图可能不太适用。因为箱线图主要用于分类变量的分布比较。对于连续特征,需要先将其离散化(如分桶),或者使用其他图表(如散点图、回归线图)来分析与标签的关系。
复杂关系的局限性:
箱线图主要用于展示分布差异
,但对于复杂的因果关系或非线性关系,可能需要结合其他分析方法(如相关性分析、回归分析)来进一步验证。
精简总结:
箱线图通过展示数据的五数概括和分布情况,可以帮助分析分类特征与连续标签之间的关系。它特别适合用于比较不同特征值对应的标签分布差异和检测异常值。对于连续特征,可能需要先进行离散化处理,或者使用其他图表进行分析。
从箱线图可以看出vedio_特征为True的手机价格分布在大体上是比False的要高的,即vedio特征的有无会影响price
2. 结构化数据预处理
2.1 筛选特征
使用 pandas 拷贝一份数据集,命名为 df,取 ‘price (USD)’ 为标签 y, 其他为特征集合 X,删除 X 中无关特征,只保留:‘inches’, ‘battery’, ‘ram (GB)’, ‘weight (g)’, ‘storage (GB) 等特征,统计 name 特征中包含 ‘pro’ 或 ‘max’ 的样本,新建布尔特征 ‘has_pro_or_max’。
# 拷贝一份数据来做为模型训练前的预处理,不破坏原数据
df = data.copy()
X = df[['inches', 'battery', 'ram(GB)', 'weight(g)', 'storage(GB)']] #, *video_feature]
y = df['price(USD)']
X['has_pro_or_max'] = data['phone_name'].map(lambda x:1 if 'Pro' in x or 'Max' in x else 0)
# X['has_pro_or_max'] = df['phone_name'].str.contains('pro|max',case=False,regex=True).astype(int)
X
说明:
X['has_pro_or_max'] = data['phone_name'].map(lambda x:1 if 'Pro' in x or 'Max' in x else 0)
通过
map()
方法和
lambda
函数,为每个手机名称检查是否包含“Pro”或“Max”字样
如果包含,则返回
1
,表示该手机名称中包含“Pro”或“Max”;如果不包含,则返回
0
这个新特征
has_pro_or_max
被添加到特征集
X
中,用于捕捉品牌型号中可能影响价格的关键词
# X['has_pro_or_max'] = df['phone_name'].str.contains('pro|max', case=False, regex=True).astype(int)
使用str.contains()方法检查phone_name列中是否包含“pro”或“max”(不区分大小写)
case=False:忽略大小写
regex=True:允许使用正则表达式
astype(int):将布尔值(True/False)转换为整数(1/0)
这种方法与map()和lambda函数的效果相同,但更简洁
2.2 特征标签归一化及编码
编写数据预处理函数 preprocessing,对标签和特征用 sklearn 中的 StandardScaler 进行归一化。
并且在该函数中,调用接口进行划分 80% 数据为训练集,20% 数据为测试集,函数的返回值为训练集和测试集的特征和标签。
调用该函数进行数据预处理和数据集划分,并打印出训练集和测试集的数组形状。
# 对标签和特征归一化,切分数据集
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import numpy as np
def df_preprocessing(X,y):
std = StandardScaler()
X = std.fit_transform(X)
y = std.fit_transform(y.values.reshape(-1,1))
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=42)
return X_train,X_test,y_train,y_test
X_train,X_test,y_train,y_test = df_preprocessing(X,y)
#X_train.shape,X_test.shape,y_train.shape,y_test.shape
print('Number transactions X_train dataset:',X_train.shape)
print('Number transactions y_train dataset:',y_train.shape)
print('Number transactions X_test dataset:',X_test.shape)
print('Number transactions y_test dataset:',y_test.shape)
说明
:
def df_preprocessing(X, y):
std = StandardScaler()
X = std.fit_transform(X)
y = std.fit_transform(y.values.reshape(-1,1))
StandardScaler
的使用
:
对特征
X
进行标准化:
X = std.fit_transform(X)
。
对标签
y
进行标准化:
y = std.fit_transform(y.values.reshape(-1, 1))
。
y.values.reshape(-1, 1)
:将
y
从一维数组转换为二维数组,因为
StandardScaler
需要二维输入
。
改进建议
标签是否需要标准化?
在许多回归任务中,标签不需要标准化,因为模型的输出可以直接与原始标签进行比较;如果对标签进行标准化,后续需要将预测结果反向转换为原始尺度
如果确实需要标准化标签,建议在预测后进行反标准化:
y_pred = std.inverse_transform(y_pred)
保存标准化器的状态
在实际应用中,标准化器(StandardScaler)的状态(均值和标准差)需要保存,以便在模型部署时对新数据进行相同的标准化处理
可以通过 joblib 或 pickle 保存标准化器:
from joblib import dump
dump(std, 'scaler.joblib')
处理异常值
在标准化之前,建议检查数据中是否存在异常值,因为异常值会对标准化产生较大影响