You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python处理CSV生成Pyvis可视化数据时节点缺失问题求助

问题根因

原来的代码仅将接触发起方存入节点列表,未收录仅作为接收方存在的人员,同时没有提前存储全量人员的角色、家族属性,导致纯接收方节点无法被正确写入nodes.csv。

原生代码修复方案

修改点1:新增全量人员属性存储,补充收录接收方节点

在全局变量区域新增person_attr = {}用于存储所有人的角色、家族信息。修改generate_parsed_data函数内的节点添加逻辑:

def generate_parsed_data():
    global nodes, parsed_data, person_attr
    print("parsing dataset:")
    headings = []
    # 改用with自动管理文件句柄,避免资源泄漏
    with open(basepath + "db.csv", "r") as excel_file, open(basepath + "proof.csv", "w") as proof_file:
        proof_file.write("Source,Target,Contract count,Role,Family\n")
        for line in excel_file:
            parts = line.rstrip().split(',')
            if not headings:
                headings = parts
                continue
            # 先存储当前行接收方的属性
            target_name = parts[0]
            person_attr[target_name] = (parts[-2], parts[-1])
            for name, item in zip(headings, parts):
                if item.isdigit():
                    parsed_data.append(f"{target_name},{name},{item},{parts[-2]},{parts[-1]}")
                    proof_file.write(f"{target_name},{name},{item},{parts[-2]},{parts[-1]}\n")
                    # 同时添加发起方和接收方到节点列表
                    nodes.append(target_name)
                    nodes.append(name)
    nodes = list(dict.fromkeys(nodes))
    print(f"总节点数:{len(nodes)}")

修改点2:重写节点生成逻辑,遍历全量节点

def generate_node_data():
    global node_data
    print("tinkering node data:")
    with open(basepath + "nodes.csv", "w") as nodes_file:
        for node in nodes:
            # 从预存的属性字典取节点的角色、家族信息,无匹配时默认填未知
            role, family = person_attr.get(node, ("未知", "未知"))
            contact_count = get_contact_count(node)
            node_line = f"{node},{role},{family},{contact_count}"
            node_data.append(node_line)
        node_data = list(dict.fromkeys(node_data))
        for line in node_data:
            nodes_file.write(f"{line}\n")
更优工具选型建议

推荐直接使用pandas完成转换,代码量可缩减70%,且避免手动遍历的逻辑错误:

  1. 用pandas.read_csv读取原始CSV
  2. 用melt函数直接将宽表(行是接收方、列是发起方)转换为边表的长表格式
  3. 单独提取人员属性表,批量关联计算节点的接触次数

示例代码如下:

import pandas as pd
basepath = "/home/user/netmap/rc/"
# 读取原始数据
df = pd.read_csv(basepath + "db.csv")
# 提取人员属性表:姓名、角色、家族,将下面的「接收方列名」替换为原始CSV第一列的实际列名
person_attr = df[["接收方列名", "Role", "Family"]].set_index("接收方列名").to_dict("index")
# 宽表转长表生成边数据
edge_df = df.melt(id_vars=["接收方列名", "Role", "Family"], var_name="Source", value_name="Contract count")
edge_df = edge_df.rename(columns={"接收方列名": "Target"})
# 过滤接触次数为数字的有效行
edge_df = edge_df[edge_df["Contract count"].apply(lambda x: str(x).isdigit())]
# 生成proof.csv
edge_df.to_csv(basepath + "proof.csv", index=False)
# 生成edges.csv
edge_df[["Source", "Target", "Contract count"]].to_csv(basepath + "edges.csv", index=False, header=False)
# 计算每个节点的接触次数
all_nodes = pd.concat([edge_df["Source"], edge_df["Target"]]).unique()
node_list = []
for node in all_nodes:
    cnt = len(pd.concat([edge_df[edge_df["Source"]==node]["Target"], edge_df[edge_df["Target"]==node]["Source"]]).unique())
    role = person_attr[node]["Role"]
    family = person_attr[node]["Family"]
    node_list.append([node, role, family, cnt])
node_df = pd.DataFrame(node_list, columns=["Name", "Role", "Family", "ContactCount"])
node_df.to_csv(basepath + "nodes.csv", index=False, header=False)

内容的提问来源于stack exchange,提问作者asatru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 03:57:02