Python合并站点DataFrame、K-Means聚类及结果可视化实现方法
需求可行性判断
该需求完全可实现。核心实现逻辑是先对齐两类站点的时序观测数据,构造站点配对的多维度特征,再通过K-Means聚类划分特征相似的站点组,最终筛选出同组内关联度最高的空气-土壤站点对作为匹配结果,全流程可通过Python数据科学生态完成。
具体操作步骤
1 安装依赖库
先安装流程需要的第三方库,执行命令:pip install pandas numpy scikit-learn matplotlib seaborn
2 数据预处理与合并
首先规范两个数据集的格式,按时间维度对齐数据,生成所有可能的空气-土壤站点配对组合:
import pandas as pd import numpy as np from sklearn.cluster import KMeans from sklearn.preprocessing import StandardScaler import matplotlib.pyplot as plt import seaborn as sns # 加载/构造空气站点数据集(替换为你实际的读入代码即可) air_data = pd.DataFrame({ 'time': ['00:06:00','00:06:00','00:06:00','00:06:00', '00:07:00','00:07:00','00:07:00','00:07:00', '00:08:00','00:08:00','00:08:00','00:08:00', '00:09:00','00:09:00','00:09:00','00:09:00'], 'Air Station Code': ['St.1','St.2','St.3','St.4']*4, 'Humidity': [20,4,16,38,10,40,10,46,28,14,5,11,61,23,35,31], 'Temperature': [10,15,21,8,18,4,13,11,9,22,40,10,35,29,12,7] }).set_index('time') # 加载/构造土壤站点数据集(替换为你实际的读入代码即可) soil_data = pd.DataFrame({ 'time': ['00:06:00','00:06:00','00:07:00','00:07:00', '00:08:00','00:08:00','00:09:00','00:09:00'], 'Soil Station Code': ['St.1','St.2']*4, 'Soil Moisture': [21,40,10,47,18,34,16,30] }).set_index('time') # 统一列名格式,去除多余空格 air_data.columns = [c.strip() for c in air_data.columns] soil_data.columns = [c.strip() for c in soil_data.columns] # 按时间维度做内连接,生成同时间点的所有站点配对 merged = air_data.reset_index().merge( soil_data.reset_index(), on='time', how='inner' )
3 构造聚类特征并执行K-Means聚类
按站点对分组,提取统计特征、时序相关性特征作为聚类输入,标准化后完成聚类:
# 按空气站-土壤站配对分组,构造聚类特征 pair_features = merged.groupby(['Air Station Code', 'Soil Station Code']).agg( humid_mean=('Humidity', 'mean'), temp_mean=('Temperature', 'mean'), soil_moist_mean=('Soil Moisture', 'mean'), humid_std=('Humidity', 'std'), temp_std=('Temperature', 'std'), soil_moist_std=('Soil Moisture', 'std'), # 计算空气站指标与土壤湿度的时序相关性 corr_humid_soil=('Humidity', lambda x: x.corr(merged.loc[x.index, 'Soil Moisture'])), corr_temp_soil=('Temperature', lambda x: x.corr(merged.loc[x.index, 'Soil Moisture'])) ).reset_index() # 特征标准化,消除量纲影响 feature_cols = ['humid_mean','temp_mean','soil_moist_mean','humid_std','temp_std','soil_moist_std','corr_humid_soil','corr_temp_soil'] X = pair_features[feature_cols].values scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 用肘部法则确定最优簇数,示例数据中土壤站共2个,最优k为2 inertia = [] k_range = range(1, len(pair_features)+1) for k in k_range: km = KMeans(n_clusters=k, random_state=42, n_init='auto') km.fit(X_scaled) inertia.append(km.inertia_) # 执行聚类,簇数设置为与土壤站点总数一致即可 kmeans = KMeans(n_clusters=2, random_state=42, n_init='auto') pair_features['cluster'] = kmeans.fit_predict(X_scaled) # 提取最终匹配结果:同簇下相关性最高的站点对为匹配对 match_result = pair_features.sort_values( by=['cluster', 'corr_humid_soil', 'corr_temp_soil'], ascending=[True, False, False] ).groupby('Soil Station Code').first().reset_index()[['Soil Station Code', 'Air Station Code', 'cluster']] print("站点匹配结果:") print(match_result)
4 结果可视化
通过三类图表分别展示聚类参数选择、聚类分布、匹配站点的时序一致性:
plt.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文显示问题,可根据自己系统调整 plt.figure(figsize=(12,5)) # 子图1:肘部法则结果 plt.subplot(1,2,1) plt.plot(k_range, inertia, 'bo-') plt.xlabel('聚类簇数k') plt.ylabel('簇内平方和') plt.title('肘部法则确定最优k值') # 子图2:聚类散点分布 plt.subplot(1,2,2) sns.scatterplot(data=pair_features, x='humid_mean', y='soil_moist_mean', hue='cluster', style='Soil Station Code', s=150) for _, row in pair_features.iterrows(): plt.text(row.humid_mean+0.5, row.soil_moist_mean+0.5, f"空气站:{row['Air Station Code']}\n土壤站:{row['Soil Station Code']}", fontsize=8) plt.xlabel('平均湿度') plt.ylabel('平均土壤湿度') plt.title('站点对聚类结果分布') plt.tight_layout() plt.show() # 匹配站点时序趋势对比图 plt.figure(figsize=(12,5)) for i, soil_st in enumerate(match_result['Soil Station Code'].unique()): air_st = match_result[match_result['Soil Station Code']==soil_st]['Air Station Code'].iloc[0] plt.subplot(1,2,i+1) air_series = air_data[air_data['Air Station Code']==air_st][['Humidity','Temperature']] soil_series = soil_data[soil_data['Soil Station Code']==soil_st][['Soil Moisture']] plot_df = air_series.join(soil_series) plt.plot(plot_df.index, plot_df['Humidity'], label='空气湿度', marker='o') plt.plot(plot_df.index, plot_df['Temperature'], label='空气温度', marker='s') plt.plot(plot_df.index, plot_df['Soil Moisture'], label='土壤湿度', marker='^') plt.title(f'匹配对:土壤站{soil_st} <-> 空气站{air_st}') plt.legend() plt.xticks(rotation=45) plt.tight_layout() plt.show()
注意事项
- 实际使用时如果土壤站点总数为N,可直接将K-Means聚类簇数设为N,也可结合肘部法则、轮廓系数法校验最优簇数,避免主观设置的偏差。
- 如果手头有站点的经纬度、海拔等空间属性,可将空间距离作为特征加入聚类输入,能大幅提升站点匹配的准确率。
- 聚类前必须对所有输入特征做标准化处理,避免不同量纲的特征(如温度、湿度、土壤湿度数值范围差异大)主导聚类结果,导致匹配错误。
- 如果时序数据时间跨度更长,可额外加入时序相关系数、变化趋势一致性等特征,进一步提升匹配精度。
内容的提问来源于stack exchange,提问作者user16603056
相关产品推荐
相关产品推荐

