昆明天气数据分析与挖掘(二)- 昆明天气数据预处理

昆明天气数据预处理


前言

在数据分析和机器学习项目中,数据预处理是决定模型效果的关键步骤之一。本文将以昆明天气数据为例,详细介绍天气数据的预处理全过程,包括数据加载、清洗、特征工程等关键环节,并提供完整可复用的Python代码实现。


一、预处理目标与数据概况

昆明作为著名的"春城",其天气数据具有重要的分析价值。数据预处理的目标是:

  • 解决数据质量问题(缺失值、重复值、格式错误等)
  • 提取有价值的特征(日期特征、季节特征等)
  • 简化冗余信息(天气类型、风力等级标准化)
  • 为后续的数据分析和建模提供高质量数据集

本次处理的数据包含以下主要字段:

  • 城市与区域信息(city, district_name)
  • 日期(date)
  • 昼夜天气类型(type_day, type_night)
  • 昼夜风向风力(direction_day, wind_force_day等)
  • 温度信息(max_temperature, min_temperature)

二、预处理环境配置

首先需要配置Python环境,确保中文正常显示并设置合适的Pandas显示选项。

python 复制代码
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from pathlib import Path

def setup_environment():
    """配置绘图和Pandas环境"""
    # 设置中文正常显示
    plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Micro Hei', 'Heiti TC']
    plt.rcParams['axes.unicode_minus'] = False

    # 设置Pandas全局选项
    pd.set_option('display.max_columns', None)
    pd.set_option('display.width', 1000)
    pd.set_option('display.max_colwidth', 50)
    pd.set_option('display.expand_frame_repr', False)

三、数据加载与初步探索

在进行任何处理前,需要先加载数据并对其进行初步探索,了解数据的基本情况。该代码模块是昆明天气数据预处理的前置核心环节,一方面通过异常捕获机制安全加载CSV格式原始数据,避免文件缺失、格式错误等加载问题;另一方面对数据进行结构化探索,输出数据维度、类型、离散特征(天气类型、风力等级等)的唯一值及数量,为后续清洗和特征工程提供数据基础画像。

python 复制代码
def load_data(file_path):
    """加载数据并进行初步验证"""
    try:
        df = pd.read_csv(file_path)
        print(f"成功加载数据,共 {df.shape[0]} 行,{df.shape[1]} 列")
        return df
    except FileNotFoundError:
        raise FileNotFoundError(f"数据文件不存在: {file_path}")
    except Exception as e:
        raise Exception(f"加载数据出错: {str(e)}")


def inspect_data(df):
    """检查数据基本信息"""
    print("\n=== 数据基本信息 ===")
    df.info()

    print("\n=== 离散特征唯一值统计 ===")
    lisan_columns = [
        'city', 'district_name', 'type_day', 'type_night',
        'direction_day', 'wind_force_day', 'direction_night', 'wind_force_night'
    ]
    for column in lisan_columns:
        if column in df.columns:
            unique_vals = df[column].unique()
            print(f"{column}的唯一值有:{unique_vals},数量:{df[column].nunique()}")
        else:
            print(f"警告:列 {column} 不存在于数据中")

成功加载则输出41206行11列,直观呈现数据规模;失败则精准提示错误原因(文件不存在/格式错误等),快速定位问题。数据基本信息结果显示所有列均为object类型、无缺失值,明确后续需将日期列转datetime、温度列转数值型,且无需处理空值。

离散特征统计结果显示city仅为"昆明",district_name含多个区县;type_day/night有晴、多云、小雨等十余种取值,wind_force_day/night存在"1-2级、微风、≤3级"等不规范表述,直接支撑后续天气类型简化、风力等级标准化的需求;若缺失目标列,会即时提示异常。


四、核心预处理步骤

1. 重复值处理

该代码实现天气数据的重复值检测与删除,先统计重复记录数,若存在重复则执行删除,通过Pandas原生方法实现轻量化去重,同时打印处理前后的重复值数量,让清洗效果清晰可查。

python 复制代码
def handle_duplicates(df):
    """处理重复数据"""
    duplicate_count = df.duplicated().sum()
    print(f"\n重复值数量(处理前):{duplicate_count}")

    if duplicate_count > 0:
        df = df.drop_duplicates()
        print(f"重复值数量(处理后):{df.duplicated().sum()}")
    return df

根据执行结果显示,处理前重复值数量为3101,明确原始数据存在3101条重复记录,反映采集过程的冗余问题;处理后重复值数量为0,说明所有重复记录已被清理;去重后数据无冗余,避免重复记录干扰后续天气频率统计、温度分析等环节的准确性。

2. 日期处理

对原始数据中的日期信息进行了标准化处理,并基于该字段衍生出多个时间维度的特征。包括年份、月份、具体日期、星期几、所在周序号,以及根据月份划分的四季分类。这些特征有助于刻画天气变化的时间规律,为后续分析提供结构化的时间上下文。

python 复制代码
def process_dates(df):
    """处理日期相关特征"""
    # 日期转换
    df['date'] = pd.to_datetime(df['date'], format='%Y年%m月%d日', errors='coerce')

    # 检查日期转换错误
    invalid_dates = df['date'].isna().sum()
    if invalid_dates > 0:
        print(f"警告:有 {invalid_dates} 条日期格式不正确")

    # 提取日期特征
    df['year'] = df['date'].dt.year
    df['month'] = df['date'].dt.month
    df['day'] = df['date'].dt.day
    df['weekday'] = df['date'].dt.weekday  # 0-6,周一到周日
    df['week'] = df['date'].dt.isocalendar().week

    # 季节特征
    def get_season(month):
        if pd.isna(month):
            return '未知'
        if month in [3, 4, 5]:
            return '春季'
        elif month in [6, 7, 8]:
            return '夏季'
        elif month in [9, 10, 11]:
            return '秋季'
        else:
            return '冬季'

    df['season'] = df['month'].apply(get_season)
    return df

处理后部分数据如下图所示,处理后的数据集中新增了多列时间相关字段,每条记录均包含完整的年、月、日信息,并标注了对应的星期、周序号及所属季节。整体格式统一,无明显异常值,能够有效支持按时间维度展开的趋势分析或建模任务。

3. 天气类型简化

原始天气数据里,天气描述会细分到 "小雨""中到大雨" 等具体类型,这类细分表述会增加后续分析的复杂度。因此将这些细分类型归类合并,把各类降雨相关的表述统一归为 "雨天",降雪相关的归为 "雪天",多云、阴天类归为 "阴天",晴、少云类归为 "晴天",雾相关的归为 "雾天",同时对空值标注为 "未知",以此实现天气类型的标准化简化。

python 复制代码
def simplify_weather_types(df):
    """简化天气类型"""
    # 使用集合提高查询效率
    rain_set = {'小雨', '阵雨', '雨夹雪', '雷阵雨', '中雨', '大雨',
                '小到中雨', '中到大雨', '暴雨', '小雨-中雨',
                '大到暴雨', '中雨-大雨', '雷阵雨伴有冰雹'}
    snow_set = {'小雪', '中雪', '阵雪', '小到中雪', '中到大雪', '零散阵雪'}
    cloud_set = {'多云', '阴', '阴天'}
    sunny_set = {'晴', '少云', '局部多云'}
    fog_set = {'雾'}

    def simple_weather_type(weather_type):
        if pd.isna(weather_type):
            return '未知'
        elif weather_type in rain_set:
            return '雨天'
        elif weather_type in snow_set:
            return '雪天'
        elif weather_type in cloud_set:
            return '阴天'
        elif weather_type in sunny_set:
            return '晴天'
        elif weather_type in fog_set:
            return '雾天'
        else:
            return '其他'

    # 应用简化函数
    df['type_day'] = df['type_day'].apply(simple_weather_type)
    df['type_night'] = df['type_night'].apply(simple_weather_type)
    return df

处理后部分数据如下图所示,从处理后的数据能看到,原本细分的天气表述(比如 "晴""阴"),现在统一成了 "晴天""雨天" 等大类。简化后的天气类型更简洁规整,既保留了天气的核心属性,又避免了细分类型过多带来的分析冗余,方便后续统计不同天气类别对应的温度变化、出现频率等分析工作。

4. 风力等级标准化

原始数据里,风力的描述方式比较杂乱,像 "1-2 级""微风""≤3 级" 这些不同说法,其实都属于相近的风力范围。把这些零散的表述做了统一归类,将 "1-2 级""微风" 等都合并为 "1-3 级","3""4""3~4 级" 等统一成 "3-4 级",同时保留 "4-5 级""5-6 级" 的分类,对未匹配到的情况标注为 "未知",这样就能让风力等级的表述更规范统一。

python 复制代码
def simplify_wind_force(df):
    """简化风力等级"""
    force_map = {
        '1-2级': '1-3级',
        '微风': '1-3级',
        '微风级': '1-3级',
        '≤3级': '1-3级',
        '<3级': '1-3级',
        '1-3级': '1-3级',
        '3': '3-4级',
        '4': '3-4级',
        '3-4级级': '3-4级',
        '3~4级': '3-4级',
        '3-4级': '3-4级',
        '4-5级': '4-5级',
        '5-6级': '5-6级'
    }

    # 使用map方法进行映射转换
    df['wind_force_day'] = df['wind_force_day'].map(force_map).fillna('未知')
    df['wind_force_night'] = df['wind_force_night'].map(force_map).fillna('未知')
    return df

处理后部分数据如图所示,从处理后的数据能看到,原本不同表述的风力(比如 "1-2 级""微风"),现在都统一成了 "1-3 级" 这样的标准等级。标准化后的风力等级更规整,既保留了风力的核心区间信息,又避免了表述混乱带来的分析干扰,方便后续统计不同风力等级对应的天气、温度等关联特征。

5. 温度数据处理

温度是天气分析的核心数据,原始数据里温度带 "℃" 单位且可能存在缺失,先按区域、年月分组做前置填充(同区域同月温度有连续性),再去掉 "℃" 单位并转为整数格式,最后计算出日温差。这样既解决了单位和格式问题,也补充了温差这一实用特征。

python 复制代码
def process_temperatures(df):
    """处理温度数据"""
    # 处理缺失值
    print("\n缺失值情况(处理前):")
    print(df[['max_temperature', 'min_temperature']].isnull().sum())

    # 按区域、年、月向前填充缺失值(同区域同月的温度具有连续性)
    df['max_temperature'] = df.groupby(['district_name', 'year', 'month'])['max_temperature'].fillna(method='ffill')
    df['min_temperature'] = df.groupby(['district_name', 'year', 'month'])['min_temperature'].fillna(method='ffill')

    # 处理单位并转换为整数
    def clean_unit(temperature):
        if pd.isna(temperature):
            return np.nan
        try:
            return int(str(temperature).replace('℃', ''))
        except (ValueError, TypeError):
            return np.nan

    df['max_temperature'] = df['max_temperature'].apply(clean_unit)
    df['min_temperature'] = df['min_temperature'].apply(clean_unit)

    # 计算温差特征
    df['temp_diff'] = df['max_temperature'] - df['min_temperature']

    print("缺失值情况(处理后):")
    print(df[['max_temperature', 'min_temperature', 'temp_diff']].isnull().sum())
    return df

处理后数据如下图,从处理后的数据能看到,原本带 "℃" 的温度值(如 "19℃"),现在已转为纯数字格式。统一格式后的温度数据更便于后续计算(比如统计月均温),而温差的隐含信息也被提取出来,能直接用于分析不同天气下的温度波动情况。


五、完整流程整合与执行

为了让零散的预处理步骤形成可落地的完整流程,将环境配置、数据加载、数据检查、各类清洗操作及结果保存整合到主函数中。执行时会先完成绘图和Pandas环境的基础配置,再加载原始昆明天气数据并做初步探查,随后按"去重→日期处理→天气类型简化→风力等级标准化→温度数据清洗"的顺序,依次完成全维度的数据规整,最后将处理后的数据集保存到指定路径,形成一套闭环的预处理流程。这种模块化的整合方式,既保证了预处理步骤的有序性,也让整个过程可复现、可调整,只需运行主函数就能完成从原始数据到可用数据集的全流程转换,且保存后的文件可直接用于后续的天气数据分析或建模工作。

python 复制代码
def main():
    # 环境设置
    setup_environment()

    # 数据加载
    input_path = '../数据采集/data/昆明天气数据.csv'
    df = load_data(input_path)

    # 数据检查
    inspect_data(df)

    # 数据清洗流程
    df = handle_duplicates(df)
    df = process_dates(df)
    df = simplify_weather_types(df)
    df = simplify_wind_force(df)
    df = process_temperatures(df)

    # 保存清洗后的数据
    output_dir = Path('./data')
    output_dir.mkdir(parents=True, exist_ok=True)
    output_path = output_dir / '昆明天气数据_清洗后.csv'
    df.to_csv(output_path, index=False)
    print(f"\n清洗后的数据已保存至:{output_path}")


if __name__ == "__main__":
    main()

预处理后的部分数据如下图所示,处理后的数据集规整性显著提升,天气类型、风力等级完成标准化,温度去除单位转为纯数值;新增年、月、季节、温差等特征。数据保留核心信息且更易分析,可直接用于天气特征统计、时间维度分析等后续工作。


六、完整代码

python 复制代码
from pathlib import Path

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt


# ----------------------------
# 配置设置
# ----------------------------
def setup_environment():
    """配置绘图和Pandas环境"""
    # 设置中文正常显示
    plt.rcParams['font.sans-serif'] = ['SimHei', 'WenQuanYi Micro Hei', 'Heiti TC']
    plt.rcParams['axes.unicode_minus'] = False

    # 设置Pandas全局选项
    pd.set_option('display.max_columns', None)
    pd.set_option('display.width', 1000)
    pd.set_option('display.max_colwidth', 50)
    pd.set_option('display.expand_frame_repr', False)


# ----------------------------
# 数据加载与初步检查
# ----------------------------
def load_data(file_path):
    """加载数据并进行初步验证"""
    try:
        df = pd.read_csv(file_path)
        print(f"成功加载数据,共 {df.shape[0]} 行,{df.shape[1]} 列")
        return df
    except FileNotFoundError:
        raise FileNotFoundError(f"数据文件不存在: {file_path}")
    except Exception as e:
        raise Exception(f"加载数据出错: {str(e)}")


def inspect_data(df):
    """检查数据基本信息"""
    print("\n=== 数据基本信息 ===")
    df.info()

    print("\n=== 离散特征唯一值统计 ===")
    lisan_columns = [
        'city', 'district_name', 'type_day', 'type_night',
        'direction_day', 'wind_force_day', 'direction_night', 'wind_force_night'
    ]
    for column in lisan_columns:
        if column in df.columns:
            unique_vals = df[column].unique()
            print(f"{column}的唯一值有:{unique_vals},数量:{df[column].nunique()}")
        else:
            print(f"警告:列 {column} 不存在于数据中")


# ----------------------------
# 数据清洗函数
# ----------------------------
def handle_duplicates(df):
    """处理重复数据"""
    duplicate_count = df.duplicated().sum()
    print(f"\n重复值数量(处理前):{duplicate_count}")

    if duplicate_count > 0:
        df = df.drop_duplicates()
        print(f"重复值数量(处理后):{df.duplicated().sum()}")
    return df


def process_dates(df):
    """处理日期相关特征"""
    # 日期转换
    df['date'] = pd.to_datetime(df['date'], format='%Y年%m月%d日', errors='coerce')

    # 检查日期转换错误
    invalid_dates = df['date'].isna().sum()
    if invalid_dates > 0:
        print(f"警告:有 {invalid_dates} 条日期格式不正确")

    # 提取日期特征
    df['year'] = df['date'].dt.year
    df['month'] = df['date'].dt.month
    df['day'] = df['date'].dt.day
    df['weekday'] = df['date'].dt.weekday  # 0-6
    df['week'] = df['date'].dt.isocalendar().week

    # 季节特征
    def get_season(month):
        if pd.isna(month):
            return '未知'
        if month in [3, 4, 5]:
            return '春季'
        elif month in [6, 7, 8]:
            return '夏季'
        elif month in [9, 10, 11]:
            return '秋季'
        else:
            return '冬季'

    df['season'] = df['month'].apply(get_season)
    return df


def simplify_weather_types(df):
    """简化天气类型"""
    # 使用集合提高查询效率
    rain_set = {'小雨', '阵雨', '雨夹雪', '雷阵雨', '中雨', '大雨',
                '小到中雨', '中到大雨', '暴雨', '小雨-中雨',
                '大到暴雨', '中雨-大雨', '雷阵雨伴有冰雹'}
    snow_set = {'小雪', '中雪', '阵雪', '小到中雪', '中到大雪', '零散阵雪'}
    cloud_set = {'多云', '阴', '阴天'}
    sunny_set = {'晴', '少云', '局部多云'}
    fog_set = {'雾'}

    def simple_weather_type(weather_type):
        if pd.isna(weather_type):
            return '未知'
        elif weather_type in rain_set:
            return '雨天'
        elif weather_type in snow_set:
            return '雪天'
        elif weather_type in cloud_set:
            return '阴天'
        elif weather_type in sunny_set:
            return '晴天'
        elif weather_type in fog_set:
            return '雾天'
        else:
            return '其他'

    # 使用矢量化操作提高效率
    df['type_day'] = df['type_day'].apply(simple_weather_type)
    df['type_night'] = df['type_night'].apply(simple_weather_type)
    return df


def simplify_wind_force(df):
    """简化风力等级"""
    force_map = {
        '1-2级': '1-3级',
        '微风': '1-3级',
        '微风级': '1-3级',
        '≤3级': '1-3级',
        '<3级': '1-3级',
        '1-3级': '1-3级',
        '3': '3-4级',
        '4': '3-4级',
        '3-4级级': '3-4级',
        '3~4级': '3-4级',
        '3-4级': '3-4级',
        '4-5级': '4-5级',
        '5-6级': '5-6级'
    }

    # 使用map方法更高效
    df['wind_force_day'] = df['wind_force_day'].map(force_map).fillna('未知')
    df['wind_force_night'] = df['wind_force_night'].map(force_map).fillna('未知')
    return df


def process_temperatures(df):
    """处理温度数据"""
    # 处理缺失值
    print("\n缺失值情况(处理前):")
    print(df[['max_temperature', 'min_temperature']].isnull().sum())

    # 按区域、年、月向前填充缺失值
    df['max_temperature'] = df.groupby(['district_name', 'year', 'month'])['max_temperature'].fillna(method='ffill')
    df['min_temperature'] = df.groupby(['district_name', 'year', 'month'])['min_temperature'].fillna(method='ffill')

    # 处理单位并转换为整数
    def clean_unit(temperature):
        if pd.isna(temperature):
            return np.nan
        try:
            return int(str(temperature).replace('℃', ''))
        except (ValueError, TypeError):
            return np.nan

    df['max_temperature'] = df['max_temperature'].apply(clean_unit)
    df['min_temperature'] = df['min_temperature'].apply(clean_unit)

    # 计算温差
    df['temp_diff'] = df['max_temperature'] - df['min_temperature']

    print("缺失值情况(处理后):")
    print(df[['max_temperature', 'min_temperature', 'temp_diff']].isnull().sum())
    return df


# ----------------------------
# 主函数
# ----------------------------
def main():
    # 环境设置
    setup_environment()

    # 数据加载
    input_path = '../数据采集/data/昆明天气数据.csv'
    df = load_data(input_path)

    # 数据检查
    inspect_data(df)

    # 数据清洗流程
    df = handle_duplicates(df)
    df = process_dates(df)
    df = simplify_weather_types(df)
    df = simplify_wind_force(df)
    df = process_temperatures(df)

    # 保存清洗后的数据
    output_dir = Path('./data')
    output_dir.mkdir(parents=True, exist_ok=True)
    output_path = output_dir / '昆明天气数据_清洗后.csv'
    df.to_csv(output_path, index=False)
    print(f"\n清洗后的数据已保存至:{output_path}")


if __name__ == "__main__":
    main()
相关推荐
艾上编程3 小时前
第二章——数据分析场景之用Python进行CSV/Excel数据清洗:为数据分析筑牢根基
python·数据分析·excel
艾上编程4 小时前
第二章——数据分析场景之Python数据可视化:用Matplotlib与Seaborn绘制洞察之图
python·信息可视化·数据分析
databook5 小时前
数据点的“社交距离”:衡量它们之间的相似与差异
python·数据挖掘·数据分析
gzroy5 小时前
智能体+MCP+NL2SQL构建一个智能数据分析应用(一)
人工智能·数据分析
TVtoPP6 小时前
使用StockTV API获取印度股票数据:完整Python实战指南
开发语言·后端·python·金融·数据分析
zandy10118 小时前
当BI遇见AI Agent:衡石科技如何重塑企业数据分析工作流
人工智能·科技·数据分析·ai agent·data agent
B站计算机毕业设计之家17 小时前
基于大数据热门旅游景点数据分析可视化平台 数据大屏 Flask框架 Echarts可视化大屏
大数据·爬虫·python·机器学习·数据分析·spark·旅游
诸神缄默不语18 小时前
专栏《数据分析与可视化实战》目录
数据分析·可视化
V搜xhliang02461 天前
AI大模型辅助临床医学科研应用、论文写作、数据分析与AI绘图学习班
人工智能·数据挖掘·数据分析