目录
[30 个地区一年的存取款数据分析](#30 个地区一年的存取款数据分析)
[步骤1: 创建模拟数据](#步骤1: 创建模拟数据)
[步骤2: 创建表格并添加变量名](#步骤2: 创建表格并添加变量名)
[步骤3: 计算每个地区的年总存款和总取款](#步骤3: 计算每个地区的年总存款和总取款)
[步骤4: 计算净存款额(存款-取款)](#步骤4: 计算净存款额(存款-取款))
[步骤5: 数据分析](#步骤5: 数据分析)
[5.1 找出存款最多的地区](#5.1 找出存款最多的地区)
[5.2 找出取款最多的地区](#5.2 找出取款最多的地区)
[5.3 找出净存款额最高的地区](#5.3 找出净存款额最高的地区)
[步骤6: 数据可视化](#步骤6: 数据可视化)
[步骤7: 月度趋势分析](#步骤7: 月度趋势分析)
[步骤1: 创建模拟数据](#步骤1: 创建模拟数据)
[步骤2: 创建嵌套表格结构](#步骤2: 创建嵌套表格结构)
[步骤3: 数据整理和分析](#步骤3: 数据整理和分析)
[3.1 计算每个地区的总招生计划、总报名人数和总录取人数](#3.1 计算每个地区的总招生计划、总报名人数和总录取人数)
[3.2 计算每所高校在各地区的平均数据](#3.2 计算每所高校在各地区的平均数据)
[步骤4: 数据可视化](#步骤4: 数据可视化)
[4.1 各地区总报名人数和总录取人数对比](#4.1 各地区总报名人数和总录取人数对比)
[4.2 各地区平均录取率](#4.2 各地区平均录取率)
[4.3 各高校平均最低分数](#4.3 各高校平均最低分数)
[步骤5: 导出数据到Excel](#步骤5: 导出数据到Excel)
[步骤1: 创建模拟数据](#步骤1: 创建模拟数据)
[步骤2: 生成24个月的模拟数据](#步骤2: 生成24个月的模拟数据)
[步骤3: 将24个月的数据汇总到同一表格](#步骤3: 将24个月的数据汇总到同一表格)
[步骤4: 数据分析](#步骤4: 数据分析)
[4.1 按月份统计招聘数量](#4.1 按月份统计招聘数量)
[4.2 按职位名称统计招聘数量](#4.2 按职位名称统计招聘数量)
[4.3 按工作地点统计招聘数量](#4.3 按工作地点统计招聘数量)
[4.4 按学历要求统计招聘数量](#4.4 按学历要求统计招聘数量)
[步骤5: 数据可视化](#步骤5: 数据可视化)
[5.1 月度招聘趋势](#5.1 月度招聘趋势)
[5.2 各职位招聘数量](#5.2 各职位招聘数量)
[5.3 各城市招聘数量](#5.3 各城市招聘数量)
[5.4 学历要求分布](#5.4 学历要求分布)
[步骤6: 薪资分析](#步骤6: 薪资分析)
[步骤7: 导出汇总数据](#步骤7: 导出汇总数据)
[步骤1: 创建模拟的共享单车数据](#步骤1: 创建模拟的共享单车数据)
[步骤2: 数据预处理](#步骤2: 数据预处理)
[2.1 检查缺失值](#2.1 检查缺失值)
[2.2 处理异常值](#2.2 处理异常值)
[2.3 处理重复值](#2.3 处理重复值)
[2.4 数据转换](#2.4 数据转换)
[2.5 添加骑行速度列(公里/小时)](#2.5 添加骑行速度列(公里/小时))
[步骤3: 数据质量评估](#步骤3: 数据质量评估)
[3.1 统计数据预处理后的基本情况](#3.1 统计数据预处理后的基本情况)
[3.2 检查骑行速度是否合理](#3.2 检查骑行速度是否合理)
[步骤4: 数据分析和可视化](#步骤4: 数据分析和可视化)
[4.1 骑行时长分布](#4.1 骑行时长分布)
[4.2 骑行距离分布](#4.2 骑行距离分布)
[4.3 每小时使用量](#4.3 每小时使用量)
[4.4 工作日vs周末使用量](#4.4 工作日vs周末使用量)
[步骤5: 热点分析](#步骤5: 热点分析)
[5.1 统计每个站点的出发和到达次数](#5.1 统计每个站点的出发和到达次数)
[5.2 可视化热门站点](#5.2 可视化热门站点)
[5.3 分析站点间的流量](#5.3 分析站点间的流量)
[步骤6: 导出预处理后的数据](#步骤6: 导出预处理后的数据)
[步骤1: 创建模拟数据](#步骤1: 创建模拟数据)
[步骤2: 创建表格并添加变量名](#步骤2: 创建表格并添加变量名)
[步骤3: 数据整理](#步骤3: 数据整理)
[3.1 计算每个分拣中心的日总货量](#3.1 计算每个分拣中心的日总货量)
[3.2 计算每个分拣中心的平均小时货量](#3.2 计算每个分拣中心的平均小时货量)
[3.3 找出每个分拣中心的峰值小时和峰值货量](#3.3 找出每个分拣中心的峰值小时和峰值货量)
[3.4 计算每个分拣中心的货量变异系数(标准差/均值)](#3.4 计算每个分拣中心的货量变异系数(标准差/均值))
[步骤4: 按小时汇总所有分拣中心的货量](#步骤4: 按小时汇总所有分拣中心的货量)
[步骤5: 数据分析和可视化](#步骤5: 数据分析和可视化)
[5.1 找出货量最大的分拣中心](#5.1 找出货量最大的分拣中心)
[5.2 找出峰值货量最大的分拣中心](#5.2 找出峰值货量最大的分拣中心)
[5.3 找出货量最稳定的分拣中心(变异系数最小)](#5.3 找出货量最稳定的分拣中心(变异系数最小))
[5.4 找出货量波动最大的分拣中心(变异系数最大)](#5.4 找出货量波动最大的分拣中心(变异系数最大))
[步骤6: 数据可视化](#步骤6: 数据可视化)
[6.1 所有分拣中心的日内货量变化](#6.1 所有分拣中心的日内货量变化)
[6.2 日总货量TOP10的分拣中心](#6.2 日总货量TOP10的分拣中心)
[6.3 小时总货量变化趋势](#6.3 小时总货量变化趋势)
[6.4 分拣中心聚类分析(基于日内货量模式)](#6.4 分拣中心聚类分析(基于日内货量模式))
[步骤7: 导出数据](#步骤7: 导出数据)
[步骤1: 创建模拟数据](#步骤1: 创建模拟数据)
[1.1 创建蔬菜基本信息表](#1.1 创建蔬菜基本信息表)
[1.2 创建蔬菜](#1.2 创建蔬菜)价格表
[1.3 创建蔬菜销量表](#1.3 创建蔬菜销量表)
[步骤2: 表格联接](#步骤2: 表格联接)
[2.1 将基本信息表与价格表联接](#2.1 将基本信息表与价格表联接)
[2.2 将上述结果与销量表联接](#2.2 将上述结果与销量表联接)
[步骤3: 数据处理和分析](#步骤3: 数据处理和分析)
[3.1 计算销售额](#3.1 计算销售额)
[3.2 按类别汇总](#3.2 按类别汇总)
[3.3 按产地汇总](#3.3 按产地汇总)
[3.4 按蔬菜汇总](#3.4 按蔬菜汇总)
[3.5 按日期汇总](#3.5 按日期汇总)
[步骤6: 导出数据](#步骤6: 导出数据)
[步骤1: 创建模拟数据](#步骤1: 创建模拟数据)
[1.1 创建监测站信息](#1.1 创建监测站信息)
[1.2 创建空气质量监测数据](#1.2 创建空气质量监测数据)
[步骤2: 同步时间表](#步骤2: 同步时间表)
[2.1 创建完整的时间戳序列(所有监测站的时间戳并集)](#2.1 创建完整的时间戳序列(所有监测站的时间戳并集))
[2.2 为每个监测站创建同步后的数据](#2.2 为每个监测站创建同步后的数据)
[2.3 合并所有监测站的数据](#2.3 合并所有监测站的数据)
[步骤3: 缺失值处理](#步骤3: 缺失值处理)
[3.1 统计缺失值情况](#3.1 统计缺失值情况)
[3.2 使用线性插值处理缺失值](#3.2 使用线性插值处理缺失值)
[3.3 再次统计缺失值情况](#3.3 再次统计缺失值情况)
[步骤4: 计算空气质量指数(AQI)](#步骤4: 计算空气质量指数(AQI))
[4.1 定义各指标的浓度限值和对应的IAQI计算函数](#4.1 定义各指标的浓度限值和对应的IAQI计算函数)
[4.2 定义计算IAQI的函数](#4.2 定义计算IAQI的函数)
[4.3 计算各指标的IAQI](#4.3 计算各指标的IAQI)
[4.4 计算AQI(取各指标IAQI的最大值)](#4.4 计算AQI(取各指标IAQI的最大值))
[4.5 确定首要污染物](#4.5 确定首要污染物)
[4.6 确定空气质量等级](#4.6 确定空气质量等级)
[步骤5: 数据分析和可视化](#步骤5: 数据分析和可视化)
[5.1 按监测站统计AQI平均值](#5.1 按监测站统计AQI平均值)
[5.2 按空气质量等级统计记录数](#5.2 按空气质量等级统计记录数)
[5.3 按首要污染物统计记录数](#5.3 按首要污染物统计记录数)
[5.4 按小时统计平均AQI](#5.4 按小时统计平均AQI)
[5.5 可视化](#5.5 可视化)
[步骤6: 导出数据](#步骤6: 导出数据)
[步骤4: 数据可视化](#步骤4: 数据可视化)
[4.1 各类别蔬菜的总销售额](#4.1 各类别蔬菜的总销售额)
[4.2 不同产地蔬菜的平均价格](#4.2 不同产地蔬菜的平均价格)
[4.3 销量TOP10的蔬菜](#4.3 销量TOP10的蔬菜)
[4.4 每日总销售额变化趋势](#4.4 每日总销售额变化趋势)
[4.5 价格与销量的散点图](#4.5 价格与销量的散点图)
[步骤5: 高级分析](#步骤5: 高级分析)
[5.1 计算价格弹性](#5.1 计算价格弹性)
[5.2 可视化价格弹性](#5.2 可视化价格弹性)
10.5表格相关练习题
30 个地区一年的存取款数据分析
步骤1: 创建模拟数据
Matlab
% 假设我们有30个地区,12个月的存取款数据
regions = string(arrayfun(@(x) sprintf('地区%d', x), 1:30, 'UniformOutput', false));
months = string(arrayfun(@(x) sprintf('%d月', x), 1:12, 'UniformOutput', false));
% 生成随机存取款数据(单位:万元)
deposit_data = randi([1000, 5000], 30, 12); % 存款数据
withdrawal_data = randi([500, 3000], 30, 12); % 取款数据
步骤2: 创建表格并添加变量名
Matlab
deposit_table = array2table(deposit_data, 'VariableNames', months);
deposit_table.Properties.DimensionNames{1} = '地区';
deposit_table.地区 = regions;
withdrawal_table = array2table(withdrawal_data, 'VariableNames', months);
withdrawal_table.Properties.DimensionNames{1} = '地区';
withdrawal_table.地区 = regions;
步骤3: 计算每个地区的年总存款和总取款
Matlab
deposit_table.年总存款 = sum(deposit_table{:, 2:13}, 2);
withdrawal_table.年总取款 = sum(withdrawal_table{:, 2:13}, 2);
步骤4: 计算净存款额(存款-取款)
Matlab
net_deposit = table();
net_deposit.地区 = regions;
net_deposit.年总存款 = deposit_table.年总存款;
net_deposit.年总取款 = withdrawal_table.年总取款;
net_deposit.净存款额 = net_deposit.年总存款 - net_deposit.年总取款;
步骤5: 数据分析
5.1 找出存款最多的地区
Matlab
[max_deposit, max_idx] = max(net_deposit.年总存款);
fprintf('存款最多的地区是%s,存款总额为%.2f万元\n', net_deposit.地区{max_idx}, max_deposit);
5.2 找出取款最多的地区
Matlab
[max_withdrawal, max_w_idx] = max(net_deposit.年总取款);
fprintf('取款最多的地区是%s,取款总额为%.2f万元\n', net_deposit.地区{max_w_idx}, max_withdrawal);
5.3 找出净存款额最高的地区
Matlab
[max_net, max_net_idx] = max(net_deposit.净存款额);
fprintf('净存款额最高的地区是%s,净存款额为%.2f万元\n', net_deposit.地区{max_net_idx}, max_net);
步骤6: 数据可视化
Matlab
figure;
subplot(2,1,1);
bar(net_deposit.年总存款);
title('各地区年总存款');
xlabel('地区');
ylabel('存款额(万元)');
xticks(1:30);
xticklabels(net_deposit.地区);
xtickangle(45);
subplot(2,1,2);
bar(net_deposit.年总取款);
title('各地区年总取款');
xlabel('地区');
ylabel('取款额(万元)');
xticks(1:30);
xticklabels(net_deposit.地区);
xtickangle(45);
步骤7: 月度趋势分析
Matlab
monthly_deposit = sum(deposit_table{:, 2:13}, 1);
monthly_withdrawal = sum(withdrawal_table{:, 2:13}, 1);
figure;
plot(1:12, monthly_deposit, '-o', 'LineWidth', 2);
hold on;
plot(1:12, monthly_withdrawal, '-s', 'LineWidth', 2);
title('月度存取款趋势');
xlabel('月份');
ylabel('金额(万元)');
legend('总存款', '总取款');
grid on;
xticks(1:12);
xticklabels(months);
xtickangle(45);
过程
- 首先创建了30个地区和12个月的标签,然后生成了随机的存取款数据
- 将数据转换为表格格式,便于后续处理和分析
- 计算了每个地区的年总存款和总取款,并计算净存款额
- 进行了基本的数据分析,找出存款最多、取款最多和净存款额最高的地区
- 通过条形图可视化各地区的存取款情况
- 通过折线图展示了月度存取款趋势,便于观察季节性变化
12个地区的高考招生数据整理
步骤1: 创建模拟数据
Matlab
% 假设有12个地区,每个地区有5所高校的招生数据
regions = string(arrayfun(@(x) sprintf('地区%d', x), 1:12, 'UniformOutput', false));
universities = string(arrayfun(@(x) sprintf('高校%d', x), 1:5, 'UniformOutput', false));
% 生成随机招生数据
% 招生计划数、报名人数、实际录取人数、最低录取分数
plan_data = randi([100, 500], 12, 5); % 招生计划数
apply_data = randi([200, 1000], 12, 5); % 报名人数
admit_data = randi([100, 500], 12, 5); % 实际录取人数
score_data = randi([400, 700], 12, 5); % 最低录取分数
步骤2: 创建嵌套表格结构
Matlab
% 创建一个主表格,每个地区一行
admission_table = table();
admission_table.地区 = regions;
% 为每个地区创建一个包含高校数据的子表格
for i = 1:12
% 创建子表格
sub_table = table();
sub_table.高校 = universities';
sub_table.招生计划 = plan_data(i,:)';
sub_table.报名人数 = apply_data(i,:)';
sub_table.实际录取 = admit_data(i,:)';
sub_table.最低分数 = score_data(i,:)';
% 计算录取率和报录比
sub_table.录取率 = sub_table.实际录取 ./ sub_table.报名人数 * 100;
sub_table.报录比 = sub_table.报名人数 ./ sub_table.招生计划;
% 将子表格添加到主表格
admission_table.高校数据{i} = sub_table;
end
步骤3: 数据整理和分析
3.1 计算每个地区的总招生计划、总报名人数和总录取人数
Matlab
region_summary = table();
region_summary.地区 = regions;
region_summary.总招生计划 = sum(plan_data, 2);
region_summary.总报名人数 = sum(apply_data, 2);
region_summary.总录取人数 = sum(admit_data, 2);
region_summary.平均录取率 = region_summary.总录取人数 ./ region_summary.总报名人数 * 100;
region_summary.平均报录比 = region_summary.总报名人数 ./ region_summary.总招生计划;
3.2 计算每所高校在各地区的平均数据
Matlab
university_summary = table();
university_summary.高校 = universities';
university_summary.平均招生计划 = mean(plan_data, 1)';
university_summary.平均报名人数 = mean(apply_data, 1)';
university_summary.平均录取人数 = mean(admit_data, 1)';
university_summary.平均最低分数 = mean(score_data, 1)';
university_summary.平均录取率 = mean(admit_data ./ apply_data * 100, 1)';
university_summary.平均报录比 = mean(apply_data ./ plan_data, 1)';
步骤4: 数据可视化
4.1 各地区总报名人数和总录取人数对比
Matlab
figure;
bar([region_summary.总报名人数, region_summary.总录取人数]);
title('各地区总报名人数与总录取人数对比');
xlabel('地区');
ylabel('人数');
legend('报名人数', '录取人数');
xticks(1:12);
xticklabels(region_summary.地区);
xtickangle(45);
4.2 各地区平均录取率
Matlab
figure;
bar(region_summary.平均录取率);
title('各地区平均录取率');
xlabel('地区');
ylabel('录取率(%)');
xticks(1:12);
xticklabels(region_summary.地区);
xtickangle(45);
4.3 各高校平均最低分数
Matlab
figure;
bar(university_summary.平均最低分数);
title('各高校平均最低录取分数');
xlabel('高校');
ylabel('分数');
xticks(1:5);
xticklabels(university_summary.高校);
xtickangle(45);
步骤5: 导出数据到Excel
Matlab
% writetable(admission_table, '高考招生数据.xlsx');
% writetable(region_summary, '地区招生汇总.xlsx');
% writetable(university_summary, '高校招生汇总.xlsx');
过程
- 创建了12个地区和5所高校的模拟招生数据,包括招生计划、报名人数、实际录取人数和最低录取分数
- 使用嵌套表格结构组织数据,主表格包含地区信息,每个地区对应一个包含高校数据的子表格
- 计算了录取率和报录比等关键指标
- 生成了两个汇总表格:一个按地区汇总,一个按高校汇总
- 通过条形图可视化各地区报名与录取人数对比、各地区平均录取率以及各高校平均最低分数
将24个月的招聘数据汇总到同一表格
步骤1: 创建模拟数据
Matlab
% 假设我们有24个月的招聘数据,每个月份是一个单独的表格
% 每个表格包含: 职位名称、公司名称、薪资范围、工作地点、学历要求、工作经验要求
% 创建24个月份标签
months = string(arrayfun(@(x) sprintf('%d年%d月', 2021+floor((x-1)/12), mod(x-1,12)+1), 1:24, 'UniformOutput', false));
% 定义可能的职位类别
job_titles = ["软件工程师", "数据分析师", "产品经理", "市场营销", "人力资源", "财务会计", "销售代表", "客户服务"];
companies = ["公司A", "公司B", "公司C", "公司D", "公司E", "公司F", "公司G", "公司H"];
locations = ["北京", "上海", "广州", "深圳", "杭州", "成都", "武汉", "西安"];
education = ["本科", "硕士", "博士", "大专", "不限"];
experience = ["应届生", "1-3年", "3-5年", "5-10年", "10年以上"];
步骤2: 生成24个月的模拟数据
Matlab
monthly_data = cell(24, 1); % 使用cell数组存储每个月的表格
for m = 1:24
% 每个月随机生成50-100条招聘记录
num_records = randi([50, 100]);
% 随机生成数据
jobs = job_titles(randi(length(job_titles), num_records, 1));
comps = companies(randi(length(companies), num_records, 1));
locs = locations(randi(length(locations), num_records, 1));
edu = education(randi(length(education), num_records, 1));
exp = experience(randi(length(experience), num_records, 1));
% 生成薪资范围(单位:千元/月)
min_salary = randi([5, 20], num_records, 1);
max_salary = min_salary + randi([5, 15], num_records, 1);
salary = arrayfun(@(x,y) sprintf('%d-%d', x, y), min_salary, max_salary, 'UniformOutput', false);
% 创建表格
monthly_table = table();
monthly_table.职位名称 = jobs;
monthly_table.公司名称 = comps;
monthly_table.薪资范围 = salary;
monthly_table.工作地点 = locs;
monthly_table.学历要求 = edu;
monthly_table.工作经验 = exp;
% 存储到cell数组
monthly_data{m} = monthly_table;
end
步骤3: 将24个月的数据汇总到同一表格
Matlab
% 添加月份列并合并所有表格
for m = 1:24
monthly_data{m}.月份 = repmat(months(m), height(monthly_data{m}), 1);
end
% 使用vertcat垂直合并所有表格
combined_data = vertcat(monthly_data{:});
步骤4: 数据分析
4.1 按月份统计招聘数量
Matlab
monthly_count = groupcounts(combined_data, '月份');
4.2 按职位名称统计招聘数量
Matlab
job_count = groupcounts(combined_data, '职位名称');
4.3 按工作地点统计招聘数量
Matlab
location_count = groupcounts(combined_data, '工作地点');
4.4 按学历要求统计招聘数量
Matlab
education_count = groupcounts(combined_data, '学历要求');
步骤5: 数据可视化
5.1 月度招聘趋势
Matlab
figure;
plot(1:24, monthly_count.Percent, '-o', 'LineWidth', 2);
title('24个月招聘数量趋势');
xlabel('月份');
ylabel('招聘数量');
grid on;
xticks(1:24);
xticklabels(months);
xtickangle(45);
5.2 各职位招聘数量
Matlab
figure;
pie(job_count.Percent, job_count.职位名称);
title('各职位招聘数量占比');
5.3 各城市招聘数量
Matlab
figure;
barh(location_count.Percent);
title('各城市招聘数量');
xlabel('招聘数量');
ylabel('城市');
yticks(1:length(location_count.工作地点));
yticklabels(location_count.工作地点);
5.4 学历要求分布
Matlab
figure;
pie(education_count.Percent, education_count.学历要求);
title('学历要求分布');
步骤6: 薪资分析
Matlab
% 从薪资范围中提取最低薪资和最高薪资
min_sal = zeros(height(combined_data), 1);
max_sal = zeros(height(combined_data), 1);
for i = 1:height(combined_data)
salary_str = combined_data.薪资范围{i};
parts = strsplit(salary_str, '-');
min_sal(i) = str2double(parts{1});
max_sal(i) = str2double(parts{2});
end
% 添加到表格
combined_data.最低薪资 = min_sal;
combined_data.最高薪资 = max_sal;
combined_data.平均薪资 = (min_sal + max_sal) / 2;
% 按职位分析薪资
job_salary = groupsummary(combined_data, '职位名称', {'mean', 'min', 'max'}, '平均薪资');
% 可视化各职位平均薪资
figure;
bar(job_salary.平均薪资);
title('各职位平均薪资');
xlabel('职位');
ylabel('平均薪资(千元/月)');
xticks(1:length(job_salary.职位名称));
xticklabels(job_salary.职位名称);
xtickangle(45);
步骤7: 导出汇总数据
Matlab
% writetable(combined_data, '24个月招聘数据汇总.xlsx');
过程
- 创建了24个月的模拟招聘数据,包括职位名称、公司名称、薪资范围、工作地点、学历要求和工作经验
- 使用cell数组存储每个月的表格,然后通过添加月份列并使用vertcat函数将所有数据合并到一个表格中
- 进行了多维度分析:按月份、职位名称、工作地点和学历要求统计招聘数量
- 通过多种图表可视化数据:折线图展示月度趋势,饼图展示职位和学历分布,水平条形图展示城市分布
- 对薪资数据进行了特殊处理,从字符串中提取数值并计算平均薪资
- 按职位分析了薪资情况,并通过条形图展示各职位的平均薪资
共享单车数据预处理
步骤1: 创建模拟的共享单车数据
Matlab
% 假设数据包含: 单车ID、开始时间、结束时间、开始位置、结束位置、骑行时长、骑行距离
% 创建可能的单车ID
bike_ids = string(arrayfun(@(x) sprintf('B%04d', x), 1:100, 'UniformOutput', false));
% 创建位置点(假设有20个固定站点)
locations = string(arrayfun(@(x) sprintf('站点%d', x), 1:20, 'UniformOutput', false));
% 生成1000条随机骑行记录
num_records = 1000;
bike_data = table();
% 随机分配单车ID
bike_data.单车ID = bike_ids(randi(length(bike_ids), num_records, 1));
% 生成开始和结束时间(假设数据来自2023年1月)
start_dates = datetime(2023, 1, 1) + hours(randi(0, 23, num_records, 1)) + minutes(randi(0, 59, num_records, 1));
ride_durations = minutes(randi(5, 120, num_records, 1)); % 骑行时长5-120分钟
end_dates = start_dates + ride_durations;
bike_data.开始时间 = start_dates;
bike_data.结束时间 = end_dates;
% 随机分配开始和结束位置
bike_data.开始位置 = locations(randi(length(locations), num_records, 1));
bike_data.结束位置 = locations(randi(length(locations), num_records, 1));
% 计算骑行时长(分钟)
bike_data.骑行时长 = minutes(bike_data.结束时间 - bike_data.开始时间);
% 生成骑行距离(公里)
bike_data.骑行距离 = 0.2 + rand(num_records, 1) * 4.8; % 0.2-5公里
步骤2: 数据预处理
2.1 检查缺失值
Matlab
missing_values = ismissing(bike_data);
fprintf('缺失值统计:\n');
for i = 1:width(bike_data)
fprintf('%s: %d\n', bike_data.Properties.VariableNames{i}, sum(missing_values(:, i)));
end
2.2 处理异常值
Matlab
% 检查骑行时长是否异常(假设超过3小时为异常)
abnormal_duration = bike_data.骑行时长 > 180;
fprintf('\n骑行时长异常记录数: %d\n', sum(abnormal_duration));
% 检查骑行距离是否异常(假设超过10公里为异常)
abnormal_distance = bike_data.骑行距离 > 10;
fprintf('骑行距离异常记录数: %d\n', sum(abnormal_distance));
% 标记异常记录
bike_data.异常记录 = abnormal_duration | abnormal_distance;
2.3 处理重复值
Matlab
% 检查是否有完全相同的记录
[~, unique_idx] = unique(bike_data(:, 1:6), 'rows');
duplicates = setdiff(1:height(bike_data), unique_idx);
fprintf('\n重复记录数: %d\n', length(duplicates));
% 删除重复记录
bike_data = bike_data(unique_idx, :);
2.4 数据转换
Matlab
% 添加日期、星期几和小时列,便于后续分析
bike_data.日期 = date(bike_data.开始时间);
bike_data.星期几 = weekday(bike_data.开始时间);
bike_data.小时 = hour(bike_data.开始时间);
% 将星期几转换为文本
weekdays = ["日", "一", "二", "三", "四", "五", "六"];
bike_data.星期几文本 = string(arrayfun(@(x) weekdays(x), bike_data.星期几, 'UniformOutput', false));
% 添加是否周末列
bike_data.是否周末 = bike_data.星期几 == 1 | bike_data.星期几 == 7;
2.5 添加骑行速度列(公里/小时)
Matlab
bike_data.骑行速度 = bike_data.骑行距离 ./ (bike_data.骑行时长 / 60);
步骤3: 数据质量评估
3.1 统计数据预处理后的基本情况
Matlab
fprintf('\n数据预处理后基本情况:\n');
fprintf('总记录数: %d\n', height(bike_data));
fprintf('异常记录数: %d\n', sum(bike_data.异常记录));
fprintf('正常记录数: %d\n', sum(~bike_data.异常记录));
3.2 检查骑行速度是否合理
Matlab
abnormal_speed = bike_data.骑行速度 > 25 | bike_data.骑行速度 < 3; % 假设速度超过25km/h或低于3km/h为异常
fprintf('骑行速度异常记录数: %d\n', sum(abnormal_speed));
% 更新异常记录标记
bike_data.异常记录 = bike_data.异常记录 | abnormal_speed;
步骤4: 数据分析和可视化
4.1 骑行时长分布
Matlab
figure;
subplot(2,2,1);
histogram(bike_data.骑行时长(~bike_data.异常记录), 20);
title('骑行时长分布(正常数据)');
xlabel('时长(分钟)');
ylabel('频次');
4.2 骑行距离分布
Matlab
subplot(2,2,2);
histogram(bike_data.骑行距离(~bike_data.异常记录), 20);
title('骑行距离分布(正常数据)');
xlabel('距离(公里)');
ylabel('频次');
4.3 每小时使用量
Matlab
hourly_usage = groupcounts(bike_data(~bike_data.异常记录, :), '小时');
subplot(2,2,3);
bar(hourly_usage.小时, hourly_usage.Percent);
title('每小时使用量');
xlabel('小时');
ylabel('使用次数');
xticks(0:23);
4.4 工作日vs周末使用量
Matlab
weekday_weekend = groupcounts(bike_data(~bike_data.异常记录, :), '是否周末');
subplot(2,2,4);
pie(weekday_weekend.Percent, ["工作日", "周末"]);
title('工作日vs周末使用量');
步骤5: 热点分析
5.1 统计每个站点的出发和到达次数
Matlab
start_counts = groupcounts(bike_data(~bike_data.异常记录, :), '开始位置');
end_counts = groupcounts(bike_data(~bike_data.异常记录, :), '结束位置');
% 合并统计结果
location_stats = outerjoin(start_counts, end_counts, 'Keys', '开始位置', 'MergeKeys', true);
location_stats.Properties.VariableNames{1} = '站点';
location_stats.Properties.VariableNames{2} = '出发次数';
location_stats.Properties.VariableNames{3} = '到达次数';
% 填充缺失值
location_stats.出发次数(ismissing(location_stats.出发次数)) = 0;
location_stats.到达次数(ismissing(location_stats.到达次数)) = 0;
% 计算总使用次数
location_stats.总使用次数 = location_stats.出发次数 + location_stats.到达次数;
% 按总使用次数排序
location_stats = sortrows(location_stats, '总使用次数', 'descend');
5.2 可视化热门站点
figure;
subplot(2,1,1);
barh(location_stats.总使用次数(1:10));
title('热门站点TOP10');
xlabel('使用次数');
ylabel('站点');
yticks(1:10);
yticklabels(location_stats.站点(1:10));
5.3 分析站点间的流量
Matlab
% 创建站点间的流量矩阵
flow_matrix = zeros(length(locations), length(locations));
for i = 1:height(bike_data(~bike_data.异常_record, :))
if ~bike_data.异常记录(i)
start_loc = bike_data.开始位置{i};
end_loc = bike_data.结束位置{i};
start_idx = find(strcmp(locations, start_loc));
end_idx = find(strcmp(locations, end_loc));
if ~isempty(start_idx) && ~isempty(end_idx)
flow_matrix(start_idx, end_idx) = flow_matrix(start_idx, end_idx) + 1;
end
end
end
% 找出流量最大的前10条路线
[flow_values, flow_indices] = sort(flow_matrix(:), 'descend');
top_flows = flow_values(1:10);
% 获取对应的站点对
[top_i, top_j] = ind2sub(size(flow_matrix), flow_indices(1:10));
top_routes = arrayfun(@(x,y) sprintf('%s -> %s', locations{x}, locations{y}), top_i, top_j, 'UniformOutput', false);
% 可视化热门路线
subplot(2,1,2);
barh(top_flows);
title('热门路线TOP10');
xlabel('流量');
ylabel('路线');
yticks(1:10);
yticklabels(top_routes);
步骤6: 导出预处理后的数据
Matlab
% writetable(bike_data, '共享单车预处理数据.xlsx');
% writetable(location_stats, '站点使用统计.xlsx');
过程
- 创建了模拟的共享单车数据,包括单车ID、开始时间、结束时间、开始位置、结束位置、骑行时长和骑行距离
- 进行了全面的数据预处理:
- 检查并统计缺失值
- 识别并标记异常值(如过长的骑行时间或过长的骑行距离)
- 删除重复记录
- 进行数据转换,添加日期、星期几、小时和是否周末等列
- 计算骑行速度并检查是否合理
- 评估了数据质量,统计了异常记录和正常记录的数量
- 通过多种图表进行数据分析和可视化:
- 骑行时长和距离的分布直方图
- 每小时使用量的条形图
- 工作日vs周末使用量的饼图
- 进行了热点分析:
- 统计每个站点的出发和到达次数,找出热门站点
- 分析站点间的流量,找出热门路线
57个分拣中心的小时货量数据整理
步骤1: 创建模拟数据
Matlab
% 假设有57个分拣中心,记录24小时的货量数据
% 创建分拣中心ID
centers = string(arrayfun(@(x) sprintf('C%03d', x), 1:57, 'UniformOutput', false));
% 创建小时标签(0-23时)
hours = 0:23;
% 生成57个分拣中心24小时的货量数据
% 考虑到分拣中心的货量通常有日内变化模式,我们使用正弦函数加随机噪声生成数据
base_volume = 1000; % 基础货量
amplitude = 500; % 波动幅度
peak_hour = 14; % 峰值小时(下午2点)
% 创建货量数据矩阵
volume_data = zeros(57, 24);
for i = 1:57
% 每个分拣中心的基础货量和波动幅度略有不同
center_base = base_volume + randi([-200, 200]);
center_amplitude = amplitude + randi([-100, 100]);
center_peak = peak_hour + randi([-2, 2]); % 峰值时间略有不同
% 生成日内变化模式
for h = 1:24
% 使用正弦函数模拟日内变化,并添加随机噪声
hour_factor = sin(pi * (h-1-center_peak+12)/12);
volume_data(i, h) = max(0, center_base + center_amplitude * hour_factor + randn * 50);
end
end
步骤2: 创建表格并添加变量名
Matlab
volume_table = array2table(volume_data, 'VariableNames', string(hours));
volume_table.Properties.DimensionNames{1} = '分拣中心';
volume_table.分拣中心 = centers;
步骤3: 数据整理
3.1 计算每个分拣中心的日总货量
Matlab
volume_table.日总货量 = sum(volume_table{:, 2:25}, 2);
3.2 计算每个分拣中心的平均小时货量
Matlab
volume_table.平均小时货量 = mean(volume_table{:, 2:25}, 2);
3.3 找出每个分拣中心的峰值小时和峰值货量
Matlab
[peak_volumes, peak_hours] = max(volume_data, [], 2);
volume_table.峰值小时 = peak_hours - 1; % 转换为0-23小时
volume_table.峰值货量 = peak_volumes;
3.4 计算每个分拣中心的货量变异系数(标准差/均值)
Matlab
hourly_volumes = volume_table{:, 2:25};
volume_table.变异系数 = std(hourly_volumes, 0, 2) ./ mean(hourly_volumes, 2);
步骤4: 按小时汇总所有分拣中心的货量
Matlab
hourly_summary = table();
hourly_summary.小时 = hours';
hourly_summary.总货量 = sum(volume_data, 1)';
hourly_summary.平均货量 = mean(volume_data, 1)';
hourly_summary.最大货量 = max(volume_data, [], 1)';
hourly_summary.最小货量 = min(volume_data, [], 1)';
步骤5: 数据分析和可视化
5.1 找出货量最大的分拣中心
Matlab
[max_daily, max_center_idx] = max(volume_table.日总货量);
fprintf('日总货量最大的分拣中心是%s,货量为%.2f\n', volume_table.分拣中心{max_center_idx}, max_daily);
5.2 找出峰值货量最大的分拣中心
Matlab
[max_peak, max_peak_idx] = max(volume_table.峰值货量);
fprintf('峰值货量最大的分拣中心是%s,峰值货量为%.2f\n', volume_table.分拣中心{max_peak_idx}, max_peak);
5.3 找出货量最稳定的分拣中心(变异系数最小)
Matlab
[min_cv, min_cv_idx] = min(volume_table.变异系数);
fprintf('货量最稳定的分拣中心是%s,变异系数为%.4f\n', volume_table.分拣中心{min_cv_idx}, min_cv);
5.4 找出货量波动最大的分拣中心(变异系数最大)
Matlab
[max_cv, max_cv_idx] = max(volume_table.变异系数);
fprintf('货量波动最大的分拣中心是%s,变异系数为%.4f\n', volume_table.分拣中心{max_cv_idx}, max_cv);
步骤6: 数据可视化
6.1 所有分拣中心的日内货量变化
Matlab
figure;
plot(hours, volume_data', 'LineWidth', 1);
hold on;
plot(hours, hourly_summary.平均货量, 'k-', 'LineWidth', 3);
title('所有分拣中心的日内货量变化');
xlabel('小时');
ylabel('货量');
legend('平均货量', 'Location', 'best');
grid on;
xticks(hours);
6.2 日总货量TOP10的分拣中心
Matlab
sorted_centers = sortrows(volume_table, '日总货量', 'descend');
top10_centers = sorted_centers(1:10, :);
figure;
bar(top10_centers.日总货量);
title('日总货量TOP10的分拣中心');
xlabel('分拣中心');
ylabel('日总货量');
xticks(1:10);
xticklabels(top10_centers.分拣中心);
xtickangle(45);
6.3 小时总货量变化趋势
Matlab
figure;
plot(hours, hourly_summary.总货量, '-o', 'LineWidth', 2);
hold on;
plot(hours, hourly_summary.平均货量, '-s', 'LineWidth', 2);
plot(hours, hourly_summary.最大货量, '-^', 'LineWidth', 1);
plot(hours, hourly_summary.最小货量, '-v', 'LineWidth', 1);
title('小时货量变化趋势');
xlabel('小时');
ylabel('货量');
legend('总货量', '平均货量', '最大货量', '最小货量', 'Location', 'best');
grid on;
xticks(hours);
6.4 分拣中心聚类分析(基于日内货量模式)
Matlab
% 使用K-means聚类将分拣中心分为5类
num_clusters = 5;
[idx, centroids] = kmeans(volume_data, num_clusters);
% 将聚类结果添加到表格
volume_table.聚类类别 = idx;
% 可视化聚类结果
figure;
for c = 1:num_clusters
subplot(num_clusters, 1, c);
cluster_centers = volume_data(idx == c, :);
plot(hours, cluster_centers', 'LineWidth', 1);
hold on;
plot(hours, centroids(c, :), 'k-', 'LineWidth', 3);
title(sprintf('类别%d (%d个分拣中心)', c, sum(idx == c)));
xlabel('小时');
ylabel('货量');
grid on;
xticks(hours);
end
步骤7: 导出数据
Matlab
% writetable(volume_table, '分拣中心货量数据.xlsx');
% writetable(hourly_summary, '小时货量汇总.xlsx');
过程
- 创建了57个分拣中心24小时的模拟货量数据,使用正弦函数模拟日内变化模式,并添加随机噪声
- 将数据转换为表格格式,便于后续处理和分析
- 进行了数据整理,计算了每个分拣中心的日总货量、平均小时货量、峰值小时和峰值货量
- 计算了货量变异系数,用于衡量货量波动程度
- 按小时汇总了所有分拣中心的货量数据
- 进行了数据分析,找出了货量最大、峰值最大、最稳定和波动最大的分拣中心
- 通过多种图表进行数据可视化:
- 所有分拣中心的日内货量变化曲线
- 日总货量TOP10的分拣中心条形图
- 小时货量变化趋势图
- 使用K-means聚类分析将分拣中心按日内货量模式分为5类,并可视化各类别的货量模式
蔬菜商品表格的联接
步骤1: 创建模拟数据
假设我们有三个表格:蔬菜基本信息表、蔬菜价格表和蔬菜销量表
1.1 创建蔬菜基本信息表
Matlab
vegetable_names = ["白菜", "菠菜", "芹菜", "生菜", "油菜", ...
"西红柿", "黄瓜", "茄子", "辣椒", "豆角", ...
"土豆", "萝卜", "胡萝卜", "洋葱", "大蒜", ...
"南瓜", "冬瓜", "丝瓜", "苦瓜", "西葫芦"];
categories = ["叶菜类", "叶菜类", "叶菜类", "叶菜类", "叶菜类", ...
"茄果类", "瓜菜类", "茄果类", "茄果类", "豆类", ...
"根茎类", "根茎类", "根茎类", "根茎类", "根茎类", ...
"瓜菜类", "瓜菜类", "瓜菜类", "瓜菜类", "瓜菜类"];
origins = ["本地", "外地", "本地", "本地", "本地", ...
"本地", "本地", "外地", "本地", "本地", ...
"本地", "本地", "外地", "外地", "本地", ...
"本地", "本地", "本地", "本地", "本地"];
% 创建基本信息表
basic_info = table();
basic_info.蔬菜ID = string(arrayfun(@(x) sprintf('V%03d', x), 1:20, 'UniformOutput', false));
basic_info.蔬菜名称 = vegetable_names';
basic_info.类别 = categories';
basic_info.产地 = origins';
1.2 创建蔬菜价格表
Matlab
% 假设有30天的价格数据
dates = datetime(2023, 6, 1) + caldays(0:29);
% 生成随机价格数据(单位:元/公斤)
price_data = table();
price_rows = [];
for d = 1:30
for v = 1:20
price_rows = [price_rows; {dates(d), basic_info.蔬菜ID{v}, basic_info.蔬菜名称{v}, ...
2 + rand() * 8}]; % 价格在2-10元/公斤之间
end
end
price_data = cell2table(price_rows, 'VariableNames', {'日期', '蔬菜ID', '蔬菜名称', '价格'});
1.3 创建蔬菜销量表
Matlab
% 生成随机销量数据(单位:公斤)
sales_data = table();
sales_rows = [];
for d = 1:30
for v = 1:20
% 销量与价格有一定负相关关系
base_sales = 500;
price_factor = 1000 ./ price_data{(d-1)*20+v, '价格'}; % 价格越高,销量越低
random_factor = 0.8 + rand() * 0.4; % 随机波动因子
sales = base_sales * price_factor * random_factor;
sales_rows = [sales_rows; {dates(d), basic_info.蔬菜ID{v}, basic_info.蔬菜名称{v}, sales}];
end
end
sales_data = cell2table(sales_rows, 'VariableNames', {'日期', '蔬菜ID', '蔬菜名称', '销量'});
步骤2: 表格联接
2.1 将基本信息表与价格表联接
Matlab
basic_price = outerjoin(basic_info, price_data, 'Keys', '蔬菜ID', 'MergeKeys', true);
basic_price.Properties.VariableNames{1} = '蔬菜ID';
basic_price.Properties.VariableNames{2} = '蔬菜名称_basic';
basic_price.Properties.VariableNames{3} = '类别';
basic_price.Properties.VariableNames{4} = '产地';
basic_price.Properties.VariableNames{5} = '日期';
basic_price.Properties.VariableNames{6} = '蔬菜名称_price';
basic_price.Properties.VariableNames{7} = '价格';
% 删除重复的蔬菜名称列
basic_price.蔬菜名称_price = [];
2.2 将上述结果与销量表联接
Matlab
full_data = outerjoin(basic_price, sales_data, 'Keys', {'蔬菜ID', '日期'}, 'MergeKeys', true);
full_data.Properties.VariableNames{1} = '蔬菜ID';
full_data.Properties.VariableNames{2} = '蔬菜名称';
full_data.Properties.VariableNames{3} = '类别';
full_data.Properties.VariableNames{4} = '产地';
full_data.Properties.VariableNames{5} = '日期';
full_data.Properties.VariableNames{6} = '价格';
full_data.Properties.VariableNames{7} = '蔬菜名称_sales';
full_data.Properties.VariableNames{8} = '销量';
% 删除重复的蔬菜名称列
full_data.蔬菜名称_sales = [];
步骤3: 数据处理和分析
3.1 计算销售额
Matlab
full_data.销售额 = full_data.价格 .* full_data.销量;
3.2 按类别汇总
Matlab
category_summary = groupsummary(full_data, '类别', {'mean', 'sum'}, {'价格', '销量', '销售额'});
category_summary.Properties.VariableNames{1} = '类别';
category_summary.Properties.VariableNames{2} = '组数';
category_summary.Properties.VariableNames{3} = '平均价格';
category_summary.Properties.VariableNames{4} = '总销量';
category_summary.Properties.VariableNames{5} = '总销售额';
3.3 按产地汇总
Matlab
origin_summary = groupsummary(full_data, '产地', {'mean', 'sum'}, {'价格', '销量', '销售额'});
origin_summary.Properties.VariableNames{1} = '产地';
origin_summary.Properties.VariableNames{2} = '组数';
origin_summary.Properties.VariableNames{3} = '平均价格';
origin_summary.Properties.VariableNames{4} = '总销量';
origin_summary.Properties.VariableNames{5} = '总销售额';
3.4 按蔬菜汇总
Matlab
vegetable_summary = groupsummary(full_data, '蔬菜名称', {'mean', 'sum'}, {'价格', '销量', '销售额'});
vegetable_summary.Properties.VariableNames{1} = '蔬菜名称';
vegetable_summary.Properties.VariableNames{2} = '组数';
vegetable_summary.Properties.VariableNames{3} = '平均价格';
vegetable_summary.Properties.VariableNames{4} = '总销量';
vegetable_summary.Properties.VariableNames{5} = '总销售额';
3.5 按日期汇总
Matlab
date_summary = groupsummary(full_data, '日期', {'mean', 'sum'}, {'价格', '销量', '销售额'});
date_summary.Properties.VariableNames{1} = '日期';
date_summary.Properties.VariableNames{2} = '组数';
date_summary.Properties.VariableNames{3} = '平均价格';
date_summary.Properties.VariableNames{4} = '总销量';
date_summary.Properties.VariableNames{5} = '总销售额';
步骤4: 数据可视化
4.1 各类别蔬菜的总销售额
Matlab
figure;
pie(category_summary.总销售额, category_summary.类别);
title('各类别蔬菜的总销售额');
4.2 不同产地蔬菜的平均价格
Matlab
figure;
bar(origin_summary.平均价格);
title('不同产地蔬菜的平均价格');
xlabel('产地');
ylabel('平均价格(元/公斤)');
xticks(1:2);
xticklabels(origin_summary.产地);
4.3 销量TOP10的蔬菜
Matlab
sorted_vegetables = sortrows(vegetable_summary, '总销量', 'descend');
top10_vegetables = sorted_vegetables(1:10, :);
figure;
barh(top10_vegetables.总销量);
title('销量TOP10的蔬菜');
xlabel('总销量(公斤)');
ylabel('蔬菜');
yticks(1:10);
yticklabels(top10_vegetables.蔬菜名称);
4.4 每日总销售额变化趋势
Matlab
figure;
plot(date_summary.日期, date_summary.总销售额, '-o', 'LineWidth', 2);
title('每日总销售额变化趋势');
xlabel('日期');
ylabel('总销售额(元)');
grid on;
xtickangle(45);
4.5 价格与销量的散点图
Matlab
figure;
scatter(full_data.价格, full_data.销量, 'filled');
title('价格与销量的关系');
xlabel('价格(元/公斤)');
ylabel('销量(公斤)');
grid on;
% 计算相关系数
price_sales_corr = corr(full_data.价格, full_data.销量);
fprintf('价格与销量的相关系数: %.4f\n', price_sales_corr);
步骤5: 高级分析
5.1 计算价格弹性
Matlab
% 价格弹性 = 销量变化百分比 / 价格变化百分比
% 我们按蔬菜计算价格弹性
price_elasticity = table();
price_elasticity.蔬菜名称 = vegetable_names';
for v = 1:20
% 获取单个蔬菜的数据
veg_data = full_data(strcmp(full_data.蔬菜名称, vegetable_names{v}), :);
% 按价格排序
veg_data = sortrows(veg_data, '价格');
% 计算价格和销量的对数
log_price = log(veg_data.价格);
log_sales = log(veg_data.销量);
% 使用线性回归计算弹性
X = [ones(size(log_price)), log_price];
b = X \ log_sales;
elasticity = b(2); % 弹性系数
price_elasticity.价格弹性(v) = elasticity;
end
5.2 可视化价格弹性
Matlab
sorted_elasticity = sortrows(price_elasticity, '价格弹性');
figure;
barh(sorted_elasticity.价格弹性);
title('各蔬菜的价格弹性');
xlabel('价格弹性');
ylabel('蔬菜');
yticks(1:20);
yticklabels(sorted_elasticity.蔬菜名称);
grid on;
% 添加参考线
xline(0, 'r-', 'LineWidth', 2);
text(-1.5, 10, '缺乏弹性', 'Color', 'r');
text(0.5, 10, '富有弹性', 'Color', 'r');
步骤6: 导出数据
Matlab
% writetable(full_data, '蔬菜商品完整数据.xlsx');
% writetable(category_summary, '类别汇总.xlsx');
% writetable(origin_summary, '产地汇总.xlsx');
% writetable(vegetable_summary, '蔬菜汇总.xlsx');
% writetable(date_summary, '日期汇总.xlsx');
% writetable(price_elasticity, '价格弹性.xlsx');
过程
- 创建了三个模拟表格:蔬菜基本信息表、蔬菜价格表和蔬菜销量表
- 基本信息表包含蔬菜ID、名称、类别和产地
- 价格表包含30天的价格数据
- 销量表包含30天的销量数据,销量与价格有一定负相关关系
- 使用outerjoin函数将三个表格联接成一个完整的数据表
- 进行了数据处理和分析:
- 计算销售额
- 按类别、产地、蔬菜和日期进行汇总统计
- 通过多种图表进行数据可视化:
- 各类别蔬菜的总销售额饼图
- 不同产地蔬菜的平均价格条形图
- 销量TOP10的蔬菜水平条形图
- 每日总销售额变化趋势折线图
- 价格与销量的散点图,并计算相关系数
- 进行了高级分析,计算了价格弹性(销量变化百分比/价格变化百分比)
- 使用对数线性回归方法计算每种蔬菜的价格弹性
- 通过水平条形图展示各蔬菜的价格弹性,并标注缺乏弹性和富有弹性的区域
同步空气质量时间表
步骤1: 创建模拟数据
假设我们有多个空气质量监测站的数据,需要同步时间表
1.1 创建监测站信息
Matlab
stations = ["监测站A", "监测站B", "监测站C", "监测站D", "监测站E"];
locations = ["城区", "工业区", "郊区", "居民区", "商业区"];
station_info = table();
station_info.监测站ID = string(arrayfun(@(x) sprintf('S%03d', x), 1:5, 'UniformOutput', false));
station_info.监测站名称 = stations';
station_info.位置类型 = locations';
1.2 创建空气质量监测数据
Matlab
% 假设监测周期为30天,每小时记录一次
start_date = datetime(2019, 1, 1);
end_date = datetime(2019, 1, 30);
timestamps = start_date:hours(1):end_date;
% 空气质量指标: PM2.5, PM10, SO2, NO2, O3, CO
% 创建5个监测站的数据
station_data = cell(5, 1); % 使用cell数组存储每个监测站的数据
for s = 1:5
% 每个监测站的数据量可能不同(模拟不同监测站可能有缺失记录)
% 假设监测站A和C数据完整,其他监测站有部分缺失
if s == 1 || s == 3
% 数据完整
station_timestamps = timestamps;
else
% 随机缺失5-15%的数据
missing_percent = 0.05 + rand() * 0.1;
num_missing = round(length(timestamps) * missing_percent);
missing_indices = randperm(length(timestamps), num_missing);
station_timestamps = timestamps;
station_timestamps(missing_indices) = [];
end
% 生成空气质量数据
num_records = length(station_timestamps);
% PM2.5 (μg/m³)
if s == 2 % 工业区PM2.5较高
pm25 = 50 + randn(num_records, 1) * 30;
elseif s == 3 % 郊区PM2.5较低
pm25 = 20 + randn(num_records, 1) * 10;
else
pm25 = 35 + randn(num_records, 1) * 20;
end
pm25 = max(0, pm25); % 确保非负
% PM10 (μg/m³)
pm10 = pm25 + 10 + randn(num_records, 1) * 15;
pm10 = max(0, pm10);
% SO2 (μg/m³)
if s == 2 % 工业区SO2较高
so2 = 20 + randn(num_records, 1) * 10;
else
so2 = 5 + randn(num_records, 1) * 5;
end
so2 = max(0, so2);
% NO2 (μg/m³)
if s == 2 % 工业区NO2较高
no2 = 40 + randn(num_records, 1) * 20;
elseif s == 4 % 居民区NO2中等
no2 = 30 + randn(num_records, 1) * 15;
else
no2 = 20 + randn(num_records, 1) * 10;
end
no2 = max(0, no2);
% O3 (μg/m³) - 日间较高,夜间较低
hour_of_day = hour(station_timestamps);
o3_base = 50 + 40 * sin(pi * (hour_of_day - 6) / 12); % 峰值在下午
o3 = o3_base + randn(num_records, 1) * 15;
o3 = max(0, o3);
% CO (mg/m³)
if s == 2 % 工业区CO较高
co = 1.2 + randn(num_records, 1) * 0.5;
else
co = 0.8 + randn(num_records, 1) * 0.3;
end
co = max(0, co);
% 创建表格
station_table = table();
station_table.时间戳 = station_timestamps;
station_table.监测站ID = repmat(station_info.监测站ID(s), num_records, 1);
station_table.PM25 = pm25;
station_table.PM10 = pm10;
station_table.SO2 = so2;
station_table.NO2 = no2;
station_table.O3 = o3;
station_table.CO = co;
% 存储到cell数组
station_data{s} = station_table;
end
步骤2: 同步时间表
2.1 创建完整的时间戳序列(所有监测站的时间戳并集)
Matlab
all_timestamps = unique(vertcat(station_data{:}.时间戳));
all_timestamps = sort(all_timestamps);
2.2 为每个监测站创建同步后的数据
Matlab
synced_data = cell(5, 1);
for s = 1:5
% 获取原始数据
original_data = station_data{s};
% 创建新的表格,包含所有时间戳
new_table = table();
new_table.时间戳 = all_timestamps;
new_table.监测站ID = repmat(station_info.监测站ID(s), length(all_timestamps), 1);
% 初始化空气质量指标列为NaN
new_table.PM25 = NaN(length(all_timestamps), 1);
new_table.PM10 = NaN(length(all_timestamps), 1);
new_table.SO2 = NaN(length(all_timestamps), 1);
new_table.NO2 = NaN(length(all_timestamps), 1);
new_table.O3 = NaN(length(all_timestamps), 1);
new_table.CO = NaN(length(all_timestamps), 1);
% 填充已有数据
for i = 1:length(all_timestamps)
% 查找当前时间戳在原始数据中的位置
idx = find(original_data.时间戳 == all_timestamps(i));
if ~isempty(idx)
% 找到匹配项,复制数据
new_table.PM25(i) = original_data.PM25(idx);
new_table.PM10(i) = original_data.PM10(idx);
new_table.SO2(i) = original_data.SO2(idx);
new_table.NO2(i) = original_data.NO2(idx);
new_table.O3(i) = original_data.O3(idx);
new_table.CO(i) = original_data.CO(idx);
end
end
% 存储同步后的数据
synced_data{s} = new_table;
end
2.3 合并所有监测站的数据
Matlab
combined_data = vertcat(synced_data{:});
步骤3: 缺失值处理
3.1 统计缺失值情况
Matlab
missing_counts = sum(ismissing(combined_data(:, 3:8)));
fprintf('各指标缺失值统计:\n');
fprintf('PM25: %d\n', missing_counts(1));
fprintf('PM10: %d\n', missing_counts(2));
fprintf('SO2: %d\n', missing_counts(3));
fprintf('NO2: %d\n', missing_counts(4));
fprintf('O3: %d\n', missing_counts(5));
fprintf('CO: %d\n', missing_counts(6));
3.2 使用线性插值处理缺失值
Matlab
% 按监测站分组处理缺失值
for s = 1:5
station_id = station_info.监测站ID(s);
station_mask = strcmp(combined_data.监测站ID, station_id);
station_data_subset = combined_data(station_mask, :);
% 对每个空气质量指标进行插值
for col = 3:8
% 获取列名
col_name = combined_data.Properties.VariableNames{col};
% 获取数据
data = station_data_subset.(col_name);
% 找出非NaN值的索引
valid_idx = ~isnan(data);
% 如果有至少两个非NaN值,进行插值
if sum(valid_idx) >= 2
% 使用线性插值
data = interp1(find(valid_idx), data(valid_idx), 1:length(data), 'linear', 'extrap');
% 更新数据
combined_data{station_mask, col_name} = data;
end
end
end
3.3 再次统计缺失值情况
Matlab
missing_counts_after = sum(ismissing(combined_data(:, 3:8)));
fprintf('\n插值后各指标缺失值统计:\n');
fprintf('PM25: %d\n', missing_counts_after(1));
fprintf('PM10: %d\n', missing_counts_after(2));
fprintf('SO2: %d\n', missing_counts_after(3));
fprintf('NO2: %d\n', missing_counts_after(4));
fprintf('O3: %d\n', missing_counts_after(5));
fprintf('CO: %d\n', missing_counts_after(6));
步骤4: 计算空气质量指数(AQI)
4.1 定义各指标的浓度限值和对应的IAQI计算函数
Matlab
% PM2.5
pm25_breakpoints = [0, 35, 75, 115, 150, 250, 350, 500];
pm25_iaqi_breakpoints = [0, 50, 100, 150, 200, 300, 400, 500];
% PM10
pm10_breakpoints = [0, 50, 150, 250, 350, 420, 500, 600];
pm10_iaqi_breakpoints = [0, 50, 100, 150, 200, 300, 400, 500];
% SO2
so2_breakpoints = [0, 50, 150, 475, 800, 1600, 2100, 2620];
so2_iaqi_breakpoints = [0, 50, 100, 150, 200, 300, 400, 500];
% NO2
no2_breakpoints = [0, 40, 80, 180, 280, 565, 750, 940];
no2_iaqi_breakpoints = [0, 50, 100, 150, 200, 300, 400, 500];
% O3
o3_breakpoints = [0, 100, 160, 215, 265, 800];
o3_iaqi_breakpoints = [0, 50, 100, 150, 200, 300];
% CO (单位转换为mg/m³)
co_breakpoints = [0, 2, 4, 14, 24, 36, 48, 60];
co_iaqi_breakpoints = [0, 50, 100, 150, 200, 300, 400, 500];
4.2 定义计算IAQI的函数
Matlab
calculate_iaqi = @(concentration, bp_lo, bp_hi, iaqi_lo, iaqi_hi) ...
(iaqi_hi - iaqi_lo) / (bp_hi - bp_lo) * (concentration - bp_lo) + iaqi_lo;
4.3 计算各指标的IAQI
Matlab
% 初始化IAQI列
combined_data.IAQI_PM25 = NaN(height(combined_data), 1);
combined_data.IAQI_PM10 = NaN(height(combined_data), 1);
combined_data.IAQI_SO2 = NaN(height(combined_data), 1);
combined_data.IAQI_NO2 = NaN(height(combined_data), 1);
combined_data.IAQI_O3 = NaN(height(combined_data), 1);
combined_data.IAQI_CO = NaN(height(combined_data), 1);
% 计算PM2.5的IAQI
for i = 1:height(combined_data)
pm25 = combined_data.PM25(i);
% 找到对应的浓度区间
for j = 1:length(pm25_breakpoints)-1
if pm25 >= pm25_breakpoints(j) && pm25 <= pm25_breakpoints(j+1)
bp_lo = pm25_breakpoints(j);
bp_hi = pm25_breakpoints(j+1);
iaqi_lo = pm25_iaqi_breakpoints(j);
iaqi_hi = pm25_iaqi_breakpoints(j+1);
combined_data.IAQI_PM25(i) = calculate_iaqi(pm25, bp_lo, bp_hi, iaqi_lo, iaqi_hi);
break;
end
end
end
% 计算PM10的IAQI
for i = 1:height(combined_data)
pm10 = combined_data.PM10(i);
% 找到对应的浓度区间
for j = 1:length(pm10_breakpoints)-1
if pm10 >= pm10_breakpoints(j) && pm10 <= pm10_breakpoints(j+1)
bp_lo = pm10_breakpoints(j);
bp_hi = pm10_breakpoints(j+1);
iaqi_lo = pm10_iaqi_breakpoints(j);
iaqi_hi = pm10_iaqi_breakpoints(j+1);
combined_data.IAQI_PM10(i) = calculate_iaqi(pm10, bp_lo, bp_hi, iaqi_lo, iaqi_hi);
break;
end
end
end
% 计算SO2的IAQI
for i = 1:height(combined_data)
so2 = combined_data.SO2(i);
% 找到对应的浓度区间
for j = 1:length(so2_breakpoints)-1
if so2 >= so2_breakpoints(j) && so2 <= so2_breakpoints(j+1)
bp_lo = so2_breakpoints(j);
bp_hi = so2_breakpoints(j+1);
iaqi_lo = so2_iaqi_breakpoints(j);
iaqi_hi = so2_iaqi_breakpoints(j+1);
combined_data.IAQI_SO2(i) = calculate_iaqi(so2, bp_lo, bp_hi, iaqi_lo, iaqi_hi);
break;
end
end
end
% 计算NO2的IAQI
for i = 1:height(combined_data)
no2 = combined_data.NO2(i);
% 找到对应的浓度区间
for j = 1:length(no2_breakpoints)-1
if no2 >= no2_breakpoints(j) && no2 <= no2_breakpoints(j+1)
bp_lo = no2_breakpoints(j);
bp_hi = no2_breakpoints(j+1);
iaqi_lo = no2_iaqi_breakpoints(j);
iaqi_hi = no2_iaqi_breakpoints(j+1);
combined_data.IAQI_NO2(i) = calculate_iaqi(no2, bp_lo, bp_hi, iaqi_lo, iaqi_hi);
break;
end
end
end
% 计算O3的IAQI
for i = 1:height(combined_data)
o3 = combined_data.O3(i);
% 找到对应的浓度区间
for j = 1:length(o3_breakpoints)-1
if o3 >= o3_breakpoints(j) && o3 <= o3_breakpoints(j+1)
bp_lo = o3_breakpoints(j);
bp_hi = o3_breakpoints(j+1);
iaqi_lo = o3_iaqi_breakpoints(j);
iaqi_hi = o3_iaqi_breakpoints(j+1);
combined_data.IAQI_O3(i) = calculate_iaqi(o3, bp_lo, bp_hi, iaqi_lo, iaqi_hi);
break;
end
end
end
% 计算CO的IAQI
for i = 1:height(combined_data)
co = combined_data.CO(i);
% 找到对应的浓度区间
for j = 1:length(co_breakpoints)-1
if co >= co_breakpoints(j) && co <= co_breakpoints(j+1)
bp_lo = co_breakpoints(j);
bp_hi = co_breakpoints(j+1);
iaqi_lo = co_iaqi_breakpoints(j);
iaqi_hi = co_iaqi_breakpoints(j+1);
combined_data.IAQI_CO(i) = calculate_iaqi(co, bp_lo, bp_hi, iaqi_lo, iaqi_hi);
break;
end
end
end
4.4 计算AQI(取各指标IAQI的最大值)
Matlab
iaqi_columns = combined_data{:, {'IAQI_PM25', 'IAQI_PM10', 'IAQI_SO2', 'IAQI_NO2', 'IAQI_O3', 'IAQI_CO'}};
combined_data.AQI = max(iaqi_columns, [], 2);
4.5 确定首要污染物
Matlab
% 找出每个记录的IAQI最大值对应的指标
combined_data.首要污染物 = strings(height(combined_data), 1);
pollutant_names = ["PM2.5", "PM10", "SO2", "NO2", "O3", "CO"];
for i = 1:height(combined_data)
[~, max_idx] = max(iaqi_columns(i, :));
combined_data.首要污染物(i) = pollutant_names(max_idx);
end
4.6 确定空气质量等级
Matlab
combined_data.空气质量等级 = strings(height(combined_data), 1);
combined_data.等级描述 = strings(height(combined_data), 1);
for i = 1:height(combined_data)
aqi = combined_data.AQI(i);
if aqi <= 50
combined_data.空气质量等级(i) = "一级";
combined_data.等级描述(i) = "优";
elseif aqi <= 100
combined_data.空气质量等级(i) = "二级";
combined_data.等级描述(i) = "良";
elseif aqi <= 150
combined_data.空气质量等级(i) = "三级";
combined_data.等级描述(i) = "轻度污染";
elseif aqi <= 200
combined_data.空气质量等级(i) = "四级";
combined_data.等级描述(i) = "中度污染";
elseif aqi <= 300
combined_data.空气质量等级(i) = "五级";
combined_data.等级描述(i) = "重度污染";
else
combined_data.空气质量等级(i) = "六级";
combined_data.等级描述(i) = "严重污染";
end
end
步骤5: 数据分析和可视化
5.1 按监测站统计AQI平均值
Matlab
station_aqi = groupsummary(combined_data, '监测站ID', 'mean', 'AQI');
station_aqi = outerjoin(station_info, station_aqi, 'Keys', '监测站ID');
5.2 按空气质量等级统计记录数
Matlab
level_counts = groupcounts(combined_data, '等级描述');
5.3 按首要污染物统计记录数
Matlab
pollutant_counts = groupcounts(combined_data, '首要污染物');
5.4 按小时统计平均AQI
Matlab
combined_data.小时 = hour(combined_data.时间戳);
hourly_aqi = groupsummary(combined_data, '小时', 'mean', 'AQI');
5.5 可视化
5.5.1 各监测站平均AQI
Matlab
figure;
bar(station_aqi.mean_AQI);
title('各监测站平均AQI');
xlabel('监测站');
ylabel('AQI');
xticks(1:5);
xticklabels(station_aqi.监测站名称);
xtickangle(45);
5.5.2 空气质量等级分布
Matlab
figure;
pie(level_counts.Percent, level_counts.等级描述);
title('空气质量等级分布');
5.5.3 首要污染物分布
Matlab
figure;
pie(pollutant_counts.Percent, pollutant_counts.首要污染物);
title('首要污染物分布');
5.5.4 小时平均AQI变化
Matlab
figure;
plot(hourly_aqi.小时, hourly_aqi.mean_AQI, '-o', 'LineWidth', 2);
title('小时平均AQI变化');
xlabel('小时');
ylabel('AQI');
grid on;
xticks(0:23);
5.5.5 各监测站AQI时间序列
Matlab
figure;
for s = 1:5
station_id = station_info.监测站ID(s);
station_name = station_info.监测站名称{s};
station_mask = strcmp(combined_data.监测站ID, station_id);
station_data_subset = combined_data(station_mask, :);
% 按时间排序
station_data_subset = sortrows(station_data_subset, '时间戳');
% 每天取一个平均值点(减少数据量)
daily_data = groupsummary(station_data_subset, '时间戳', 'mean', 'AQI');
plot(daily_data.时间戳, daily_data.mean_AQI, 'LineWidth', 2);
hold on;
end
title('各监测站日均AQI时间序列');
xlabel('日期');
ylabel('AQI');
legend(station_info.监测站名称, 'Location', 'best');
grid on;
xtickangle(45);
步骤6: 导出数据
Matlab
% writetable(combined_data, '同步空气质量数据.xlsx');
% writetable(station_aqi, '监测站AQI统计.xlsx');
% writetable(level_counts, '空气质量等级统计.xlsx');
% writetable(pollutant_counts, '首要污染物统计.xlsx');
% writetable(hourly_aqi, '小时AQI统计.xlsx');
过程
- 创建了5个空气质量监测站的模拟数据,包括监测站信息和30天的空气质量监测数据
- 每个监测站记录PM2.5、PM10、SO2、NO2、O3和CO六项指标
- 不同位置的监测站有不同的污染物特征(如工业区PM2.5、SO2、NO2较高)
- 模拟了部分监测站有数据缺失的情况
- 进行了时间表同步:
- 创建完整的时间戳序列(所有监测站的时间戳并集)
- 为每个监测站创建包含所有时间戳的新表格,缺失值用NaN填充
- 合并所有监测站的数据
- 处理缺失值:
- 统计各指标的缺失值情况
- 使用线性插值方法处理缺失值
- 再次统计缺失值情况,验证处理效果
- 计算空气质量指数(AQI):
- 定义各指标的浓度限值和对应的IAQI计算函数
- 计算各指标的IAQI(个体空气质量指数)
- 计算AQI(取各指标IAQI的最大值)
- 确定首要污染物(IAQI最大的指标)
- 确定空气质量等级和描述
- 进行了数据分析和可视化:
- 按监测站统计AQI平均值
- 按空气质量等级和首要污染物统计记录数
- 按小时统计平均AQI
- 通过多种图表展示分析结果:各监测站平均AQI条形图、空气质量等级和首要污染物分布饼图、小时平均AQI变化折线图、各监测站AQI时间序列图