116 lines
3.9 KiB
Python
116 lines
3.9 KiB
Python
import pickle
|
||
|
||
import pandas as pd
|
||
import networkx as nx
|
||
import matplotlib.pyplot as plt
|
||
|
||
# 1. 读取并处理数据
|
||
bom_nodes = pd.read_csv('input_data/input_product_data/BomNodes.csv')
|
||
bom_nodes['Code'] = bom_nodes['Code'].astype(str)
|
||
bom_nodes.set_index('Index', inplace=True)
|
||
|
||
bom_cate_net = pd.read_csv('input_data/input_product_data/合成结点.csv')
|
||
|
||
# 2. 构建图结构
|
||
g_bom = nx.from_pandas_edgelist(bom_cate_net, source='UPID', target='ID', create_using=nx.MultiDiGraph())
|
||
|
||
# 填充每一个结点的具体内容
|
||
bom_labels_dict = {}
|
||
for index in g_bom.nodes:
|
||
try:
|
||
bom_labels_dict[index] = bom_nodes.loc[index].to_dict()
|
||
except KeyError:
|
||
print(f"节点 {index} 不存在于 bom_nodes 中")
|
||
|
||
# 分配属性给每一个结点
|
||
nx.set_node_attributes(g_bom, bom_labels_dict)
|
||
|
||
# 3. 计算每个节点的度数
|
||
degrees = dict(g_bom.degree()) # 总度数(适用于有向图)
|
||
|
||
# 4. 统计每个度数的节点数量
|
||
degree_counts = {}
|
||
for degree in degrees.values():
|
||
if degree in degree_counts:
|
||
degree_counts[degree] += 1
|
||
else:
|
||
degree_counts[degree] = 1
|
||
|
||
# 转换为排序后的列表(横坐标:度数,纵坐标:节点数)
|
||
sorted_degrees = sorted(degree_counts.keys())
|
||
sorted_counts = [degree_counts[d] for d in sorted_degrees]
|
||
|
||
# 5. 绘制度分布图
|
||
plt.figure(figsize=(12, 8)) # 增大画布尺寸
|
||
bars = plt.bar(sorted_degrees, sorted_counts, width=0.8)
|
||
plt.title('Degree Distribution In Industrial Chain', fontsize=16)
|
||
plt.xlabel('Degree', fontsize=14)
|
||
plt.ylabel('Number of Nodes', fontsize=14)
|
||
plt.grid(True, linestyle='--', alpha=0.5)
|
||
plt.xticks(rotation=45) # 如果度数较多,可以旋转x轴标签
|
||
plt.tight_layout() # 防止标签重叠
|
||
|
||
# 6. 在每个柱子上方标注数值
|
||
for bar in bars:
|
||
height = bar.get_height()
|
||
plt.text(
|
||
bar.get_x() + bar.get_width() / 2, # x坐标:柱子中心
|
||
height + max(sorted_counts) * 0.02, # y坐标:柱子顶部上方(留出空间)
|
||
f'{int(height)}', # 显示数值(转换为整数)
|
||
ha='center', # 水平居中
|
||
va='bottom', # 垂直底部对齐
|
||
fontsize=10, # 字体大小
|
||
color='black' # 字体颜色
|
||
)
|
||
|
||
# 7. 保存超高清图片(300 DPI)
|
||
output_path = "degree_distribution_with_labels.png" # 输出文件名
|
||
plt.savefig(output_path, dpi=500, bbox_inches='tight') # dpi=300 确保高分辨率
|
||
print(f"图片已保存至: {output_path}")
|
||
|
||
# 1. 加载企业网络数据
|
||
with open("firm_network.pkl", 'rb') as f:
|
||
G_firm = pickle.load(f)
|
||
print(f"Successfully loaded cached data from firm_network.pkl")
|
||
|
||
# 2. 计算企业网络的度分布
|
||
degrees_firm = dict(G_firm.degree()) # 总度数
|
||
degree_counts_firm = {}
|
||
for degree in degrees_firm.values():
|
||
if degree in degree_counts_firm:
|
||
degree_counts_firm[degree] += 1
|
||
else:
|
||
degree_counts_firm[degree] = 1
|
||
|
||
# 转换为排序后的列表
|
||
sorted_degrees_firm = sorted(degree_counts_firm.keys())
|
||
sorted_counts_firm = [degree_counts_firm[d] for d in sorted_degrees_firm]
|
||
|
||
# 3. 绘制企业网络的度分布图
|
||
plt.figure(figsize=(12, 6)) # 单独画布尺寸
|
||
plt.bar(sorted_degrees_firm, sorted_counts_firm, width=0.8)
|
||
plt.title('Degree Distribution of Firm Network', fontsize=16)
|
||
plt.xlabel('Degree (Number of Connections)', fontsize=14)
|
||
plt.ylabel('Number of Firms', fontsize=14)
|
||
plt.grid(True, linestyle='--', alpha=0.5)
|
||
plt.xticks(rotation=45)
|
||
plt.tight_layout()
|
||
|
||
# 在柱子上方标注数值
|
||
for bar in plt.gca().containers[0]: # 获取当前图中的柱子对象
|
||
height = bar.get_height()
|
||
plt.text(
|
||
bar.get_x() + bar.get_width() / 2,
|
||
height + max(sorted_counts_firm) * 0.02,
|
||
f'{int(height)}',
|
||
ha='center',
|
||
va='bottom',
|
||
fontsize=10,
|
||
color='black'
|
||
)
|
||
|
||
# 保存图片
|
||
plt.savefig("degree_distribution_firm.png", dpi=500, bbox_inches='tight')
|
||
print("企业度分布图已保存至: degree_distribution_firm.png")
|
||
|