- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
一、实验目的:
根据数据对 RainTomorrow 进行预测,熟悉探索式数据分析(EDA)
二、实验环境:
- 语言环境:python 3.8
- 编译器:Jupyter notebook
- 深度学习环境:TensorFlow
三、背景知识
“这是数据分析中我最喜欢的部分:获取枯燥的平面数据,并通过可视化将其变为现实。” — 约翰·图基
1. 定义
探索式数据分析(Exploratory Data Analysis,简称EDA)是数据分析过程中的一个关键步骤。它是指在正式进行复杂的数据分析和建模之前,对数据进行初步的、开放式的调查,以了解数据的基本特征、分布情况、变量之间的关系等诸多方面的内容。通过探索式数据分析,医学研究人员可以快速熟悉医疗数据,发现数据中的异常值、模式、趋势,为后续更深入的医学研究(如疾病预测模型构建、治疗效果评估等)提供基础和思路。
2. 主要内容
(一)数据的基本特征
- 包括数据的类型(如数值型、分类型等)、数据的规模(病例的数量、变量的数量)。例如,对于一个医疗记录数据集,需要了解其中有多少个病例记录,有多少个不同的变量(如患者年龄、性别、疾病诊断、治疗方式等)来描述患者情况。
- 数据的取值范围,如对于一个患者血压测量数据集,要知道血压值的最小值和最大值,这有助于理解患者血压的整体情况。
(二)数据分布
- 对于数值型数据,了解其分布形态很重要。常用的分布包括正态分布、偏态分布等。例如,分析患者的血糖水平分布,看是否近似正态分布,这可以通过绘制直方图来观察。
- 分类型数据的分布则关注各个类别出现的频率。比如,在一个疾病类型数据集里,查看不同疾病的患者人数占比,了解各种疾病的相对发病率。
(三)变量间的关系
- 探索变量之间的相关性,是EDA的一个重要部分。对于两个数值变量,如患者的年龄和血压值,可以计算相关系数(如皮尔逊相关系数)来衡量它们之间线性关系的强弱。
- 对于分类变量和数值变量之间的关系,可以通过分组统计等方式来探索。比如,分析不同疾病类型患者的住院天数(数值变量)与疾病严重程度(分类变量,可分为轻度、中度、重度等)之间的关系,按疾病严重程度分组统计平均住院天数。
- 还可以使用散点图、箱线图等可视化工具来展示变量间的关系。例如,用散点图展示患者体重和体脂率之间的关系,用箱线图展示不同疾病患者的白细胞计数分布情况。
3. 常用方法和工具
(一)可视化方法
- 直方图:用于展示数值型数据的分布。例如,在分析患者的药物剂量分布时,直方图可以直观地显示不同剂量区间的患者人数分布情况。
- 箱线图:可以展示数据的四分位数、异常值等信息。比如,在比较不同治疗组患者的康复时间时,箱线图能够清晰地呈现各治疗组康复时间的分布差异,包括中位数、上下四分位数以及是否存在异常长或短的康复时间。
- 散点图:主要用于展示两个数值变量之间的关系。例如,在研究患者的身高和体重之间的关系时,散点图可以帮助我们观察它们是否存在线性或其他类型的关系。
- 柱状图:适合展示分类数据的频率或数量。比如,在统计不同年龄段患者患某种疾病的人数时,柱状图可以清晰地显示各年龄段的患病情况。
(二)统计量计算
- 计算均值、中位数、众数等中心趋势统计量,来了解数据的集中位置。例如,在分析一组患者的体温数据时,均值可以反映整体的平均体温水平,中位数则更能抵抗极端值的影响,众数可以告诉我们出现次数最多的体温值是多少。
- 计算标准差、方差等离散程度统计量,用于衡量数据的分散情况。例如,在比较两种治疗方法对患者症状改善程度的稳定性时,方差较小的治疗方法说明其效果更稳定。
- 对于分类数据,可以计算类别频率、比例等统计量。例如,在分析医院不同科室的患者就诊人数分布时,计算每个科室的患者比例,以了解各科室的业务繁忙程度。
四、导入数据
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Activation, Dropout
from tensorflow.keras.callbacks import EarlyStopping
from tensorflow.keras.layers import Dropout
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.metrics import r2_score
from sklearn.metrics import mean_absolute_error , mean_absolute_percentage_error , mean_squared_errordata = pd.read_csv("weatherAUS.csv")
df = data.copy()
data.head()
data.describe()
data.describe() 是Pandas库中DataFrame对象的一个方法,它用于生成数据的快速统计摘要。这个方法会返回一个新的DataFrame,其中包含以下统计信息:
count:非空值的数量
mean:平均值
std:标准差
min:最小值
25%:第一四分位数(Q1),即数据中所有数值由小到大排列后,位于25%位置的数值
50%:中位数(Q2),即数据中所有数值由小到大排列后,位于中间位置的数值
75%:第三四分位数(Q3),即数据中所有数值由小到大排列后,位于75%位置的数值
max:最大值
data.dtypes
以上输出显示了data DataFrame中每一列的数据类型。以下是每个部分的含义:
- 列名:每一行左侧的名称代表DataFrame中的一列。例如,Date、Location、MinTemp等。
- 数据类型:每一行右侧的值表示相应列的数据类型。以下是常见的数据类型及其含义:
- object:通常用于存储字符串(文本)数据,也可以用于存储混合数据类型(如包含不同类型的数据的列表)。
- float64:表示浮点数,通常用于存储小数和实数。
- int64:表示整数,但在这个输出中没有显示。如果有整数类型的列,它们会显示为int64。
具体到这个输出:
- Date 和 Location 列的数据类型是 object,这意味着这两列包含文本数据。通常,Date 列可能需要转换为日期时间格式(datetime)以进行更有效的处理。
- MinTemp、MaxTemp、Rainfall、Evaporation、Sunshine、WindGustSpeed、WindSpeed9am、WindSpeed3pm、Humidity9am、Humidity3pm、Pressure9am、Pressure3pm、Cloud9am、Cloud3pm、Temp9am 和 Temp3pm 列的数据类型是 float64,这表明这些列包含浮点数,可能是与天气相关的测量值。
- WindGustDir、WindDir9am、WindDir3pm 和 RainToday、RainTomorrow 列的数据类型是 object,这些列可能包含分类数据,例如风向或是否下雨的指示。
**这个信息对于数据预处理非常重要,因为不同类型的数据可能需要不同的处理方法。**例如,数值型数据可以进行数学运算,而文本数据可能需要转换为数值编码或进行其他形式的预处理。
#将数据转换为日期时间格式
data['Date'] = pd.to_datetime(data['Date'])data['year'] = data['Date'].dt.year
data['Month'] = data['Date'].dt.month
data['day'] = data['Date'].dt.daydata.head()
这里将 DataFrame data 中 ‘Date’ 列的数据类型从 object(通常是字符串)转换为 datetime64 类型。
这样做的好处是,转换后的日期时间数据可以进行更复杂的时间序列操作,例如日期的加减、日期范围的选择、时间序列的重采样等。
此外,datetime对象在数据分析和可视化中通常更容易处理,因为它们可以自动按照时间顺序排序,并且可以方便地提取日期的各个组成部分(如年、月、日等)。
data.drop('Date',axis=1,inplace=True)
data.columns
五、探索式数据分析(EDA)
1. 数据相关性搜索
# 确定数值列
numerical_data = data.select_dtypes(include=[np.number])# 计算数值列的相关性矩阵
corr_matrix = numerical_data.corr()# 绘制热力图
plt.figure(figsize=(15, 13))
ax = sns.heatmap(corr_matrix, square=True, annot=True, fmt='2f')
ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
plt.show()
select_dtypes(include=[np.number]) 用于选择所有数值类型的列。这样,在计算相关性时,只会考虑数值数据,从而避免类型转换错误。
这段代码用于生成一个热力图(heatmap),显示变量之间的相关性。
看热力图的步骤:
1. 了解热力图的基本结构
- 热力图通常是一个矩阵形式的图表,其中行和列分别代表不同的变量。
2. 观察颜色编码
- 首先确定热力图所使用的颜色编码方案。一般来说,较暖的颜色(如红色、橙色)表示较强的正相关关系,较冷的颜色(如蓝色)表示较强的负相关关系,白色或接近白色的颜色表示相关性较弱或接近零。
- 在热力图中,可以看到各种数字和颜色的组合。例如,数字接近 1 且颜色较暖的区域表示两个变量之间有较强的正相关关系;数字接近 -1 且颜色较冷的区域表示有较强的负相关关系;数字接近 0 且颜色较浅的区域表示相关性较弱。
3. 解读数值
- 仔细观察热力图中的数值。这些数值通常是相关系数,用于衡量两个变量之间的线性关系强度。相关系数的取值范围在 -1 到 1 之间。
- 例如,在“MaxTemp”和“Temp3pm”这两个变量对应的区域,数值接近 1,说明最高温度和下午3点温度之间有强正相关关系。而在一些变量对之间,数值可能接近 0 或接近 -1,分别表示相关性较弱或负相关。
4. 分析变量关系
- 从行和列的标签中确定不同的变量。在上面热力图中,变量包括温度(MinTemp、MaxTemp、Temp9am、Temp3pm 等)、降雨量(Rainfall)、蒸发量(Evaporation)、风向(WindGustDir、WindDir9am、WindDir3pm 等)、风速(WndGustSpeed、WindSpeed9am、WindSpeed3pm 等)、湿度(Humidity9am、Humidity3pm)、气压(Pressure9am、Pressure3pm)、云量(Cloud9am、Cloud3pm)等。
- 观察不同变量之间的相关性。例如,你可能会发现温度和阳光照射(Sunshine)之间有一定的正相关关系,因为在阳光充足的情况下,温度往往会升高。而降雨量和湿度可能也有一定的正相关关系。
- 注意异常值和强相关关系。如果某个变量对之间的相关性非常强(接近 1 或 -1),这可能值得进一步研究。同时,也要注意热力图中的异常值,即与其他区域颜色明显不同的部分,这可能表示数据中的特殊情况或错误。
5. 结合实际情况理解
- 将热力图中的结果与实际的气象知识和经验相结合。例如,你知道在某些地区,风向和降雨量可能有一定的关系,或者温度和季节有一定的变化规律。这些实际知识可以帮助你更好地理解热力图中的结果。
- 考虑数据的来源和背景。了解数据是在什么时间、地点收集的,以及数据的收集方法和准确性,可以帮助你更准确地解读热力图。
总之,看热力图需要综合考虑颜色编码、数值、变量关系和实际情况等多个方面,以便从中提取有价值的信息。
2. 是否会下雨
# 设置样式和调色板
sns.set(style="whitegrid", palette="Set2")# 创建一个 1 行 2 列的图像布局
fig, axes = plt.subplots(1, 2, figsize=(10, 4)) # 图形尺寸调大 (10, 4)# 图表标题样式
title_font = {'fontsize': 14, 'fontweight': 'bold', 'color': 'darkblue'}# 第一张图:RainTomorrow
sns.countplot(x='RainTomorrow', data=data, ax=axes[0], edgecolor='black') # 添加边框
axes[0].set_title('Rain Tomorrow', fontdict=title_font) # 设置标题
axes[0].set_xlabel('Will it Rain Tomorrow?', fontsize=12) # X轴标签
axes[0].set_ylabel('Count', fontsize=12) # Y轴标签
axes[0].tick_params(axis='x', labelsize=11) # X轴刻度字体大小
axes[0].tick_params(axis='y', labelsize=11) # Y轴刻度字体大小# 第二张图:RainToday
sns.countplot(x='RainToday', data=data, ax=axes[1], edgecolor='black') # 添加边框
axes[1].set_title('Rain Today', fontdict=title_font) # 设置标题
axes[1].set_xlabel('Did it Rain Today?', fontsize=12) # X轴标签
axes[1].set_ylabel('Count', fontsize=12) # Y轴标签
axes[1].tick_params(axis='x', labelsize=11) # X轴刻度字体大小
axes[1].tick_params(axis='y', labelsize=11) # Y轴刻度字体大小sns.despine() # 去除图表顶部和右侧的边框
plt.tight_layout() # 调整布局,避免图形之间的重叠
plt.show()
x=pd.crosstab(data['RainTomorrow'],data['RainToday'])
xy=x/x.transpose().sum().values.reshape(2,1)*100
yy.plot(kind="bar",figsize=(4,3),color=['#006666','#d279a6']);
3. 地理位置与下雨的关系
x=pd.crosstab(data['Location'],data['RainToday'])
# 获取每个城市下雨天数和非下雨天数的百分比
y=x/x.transpose().sum().values.reshape(-1, 1)*100
# 按每个城市的雨天百分比排序
y=y.sort_values(by='Yes',ascending=True)color=['#cc6699','#006699','#006666','#862d86','#ff9966']
y.Yes.plot(kind="barh",figsize=(15,20),color=color)
位置影响下雨,对于 Portland 来说,有 36% 的时间在下雨,而对于 Woomers 来说,只有6%的时间在下雨。
4. 湿度、压力和气温对下雨的影响
data. columns
plt.figure(figsize=(8,6))
sns.scatterplot(data=data,x='Pressure9am',y='Pressure3pm',hue='RainTomorrow');
plt.figure(figsize=(8,6))
sns.scatterplot(data=data, x='Humidity9am', y='Humidity3pm', hue='RainTomorrow');
低压与高湿度会增加第二天下雨的概率,尤其是下午 3 点的空气湿度。
plt.figure(figsize=(8,6))
sns.scatterplot(x='MaxTemp', y= 'MinTemp', data=data, hue='RainTomorrow');
当一天的最高气温和最低气温接近时,第二天下雨的概率会增加。
六、数据预处理
1. 处理缺损值
# 每列中缺失数据的百分比
data.isnull().sum() / data.shape[0] * 100
# 在该列中随机选择数进行填充
lst=['Evaporation','Sunshine','Cloud9am','Cloud3pm']for col in lst: fill_list = data[col].dropna() data[col] = data[col].fillna(pd.Series(np.random.choice(fill_list, size=len(data.index))))
整个代码段的目的就是将 data DataFrame 中指定列的所有 NaN 值用该列非 NaN 值的随机样本替换。这种方法通常用于在不破坏数据分布的情况下处理缺失数据,但它也有可能引入随机性,从而影响数据分析的结果。因此,在使用这种方法之前,应该仔细考虑其对数据分析的影响。
s = (data.dtypes == "object")
object_cols = list(s[s].index)
print(object_cols)
# inplace=True:直接修改原对象,不创建副本
# data[i].mode()[0] 返回频率出现最高的选项,众数for i in object_cols: data[i].fillna(data[i].mode()[0], inplace=True)
t = (data.dtypes == "float64")
num_cols = list(t[t].index)
num_cols
data.isnull().sum()
2. 构建数据集
from sklearn.preprocessing import LabelEncoderlabel_encoder = LabelEncoder()
for i in object_cols:data[i] = label_encoder.fit_transform(data[i])
x = data.drop(['RainTomorrow', 'day'],axis=1).values
y = data['RainTomorrow'].values
x_train, x_test, y_train, y_test = train_test_split(x,y,test_size=0.25,random_state=101)
scaler = MinMaxScaler()
scaler.fit(x_train)
x_train = scaler.transform(x_train)
x_test = scaler.transform(x_test)
七、预测是否下雨
1. 搭建神经网络
from tensorflow.keras.optimizers import Adam
model = Sequential()
model.add(Dense(units=24, activation='tanh',))
model.add(Dense(units=18, activation='tanh'))
model.add(Dense(units=23, activation='tanh'))
model.add(Dropout(0.5))
model.add(Dense(units=12, activation='tanh'))
model.add(Dropout(0.2))
model.add(Dense(units=1, activation='sigmoid'))
optimizer = tf.keras.optimizers.Adam(learning_rate=2e-4)
model.compile(loss='binary_crossentropy', optimizer=optimizer, metrics="accuracy")
early_stop = EarlyStopping(monitor='val_loss', mode='min', min_delta=0.001, verbose=1, patience=25, restore_best_weights=True)
2. 模型训练
model.fit(x=x_train, y=y_train, validation_data=(x_test, y_test), verbose=1, callbacks=[early_stop], epochs = 10, batch_size = 32 )
3. 可视化
import matplotlib.pyplot as plt
acc = model.history.history['accuracy']
val_acc = model.history.history['val_accuracy']
loss = model.history.history['loss']
val_loss = model.history.history['val_loss']
epochs_range = range(10)
plt.figure(figsize=(14, 4))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
八、总结
通过本次实验我对探索式数据分析(EDA)有了进一步的了解。回顾实验,主要通过以下几个步骤对澳大利亚多个地点大约10年的每日天气观测数据集进行了深入的探索性分析:
-
相关性分析:分析了各个气象变量之间的相关性,为后续特征选择和模型构建提供了依据。
-
降雨情况统计:通过对降雨量的统计分析,发现了不同地点和季节的降雨分布情况,为理解数据集的整体特征提供了参考。
-
地理位置与降雨的关系:探究了地理位置对降雨量的影响,发现某些地区降雨量明显高于其他地区。
-
湿度与压力对降雨的影响:通过分析湿度和气压与降雨量的关系,发现低压和高湿度会增加第二天下雨的概率。
-
气温对降雨的影响:分析了气温与降雨量的关系,为理解气温对降雨的影响提供了数据支持。
通过这些探索性分析,我对数据集有了更全面的认识,为后续的数据预处理和模型构建打下了基础。同时,我也体会到了EDA在数据分析中的重要性,它可以帮助我们发现数据中的模式和趋势,为后续的分析和建模提供指导。
在实际应用中,EDA是一个不断迭代的过程。随着对数据的深入了解,我们可能会发现新的模式和趋势,从而需要重新审视和调整我们的分析方法。所以要保持开放和灵活的心态,不断探索和尝试。