Pandas DataFrame连续索引拆分嵌套序列列表的实现与报错排查
报错的根本原因
Python列表的索引赋值仅支持操作列表当前已存在的索引位置,不会自动为不存在的索引位置开辟内存空间。
你初始化sequences = [[]]时,这个列表的总长度为1,可合法访问的索引只有0。当索引序列中断进入else分支时,seq自增为1,此时代码尝试执行sequences[1] = [index]——但列表当前根本没有索引为1的位置,既没有自动扩容,也没有提前把列表长度撑到2,自然就触发了越界报错。
需要明确的是,Python列表的索引是严格按照0到长度-1排列的连续整数,跨索引赋值的逻辑和字典添加键值对的逻辑完全不同,不支持跳跃式扩容。
Python列表动态追加元素的正确方式
要给列表新增元素,不能使用跳索引赋值的方式,必须使用列表自带的append()方法:
append()会自动把新元素放到列表末尾,同步把列表长度加1,从根源上避免索引越界- 实际使用中不需要手动维护
seq位置计数器,只要在连续序列中断时,把新的序列组作为元素append到sequences末尾,同时始终用sequences[-1]指向当前正在填充的连续组即可
修正后的可运行代码:
same_width_nodes = df.loc[df['count'] == width] # 按数值排序索引,保证连续序列判断基于数值大小而非行顺序 node_indices = same_width_nodes.sort_index().index if len(node_indices) == 0: sequences = [] else: # 初始化第一个连续序列组 sequences = [[node_indices[0]]] expected_next = node_indices[0] + 1 # 从第二个索引开始遍历分组 for idx in node_indices[1:]: if idx == expected_next: # 属于当前连续序列,追加到最后一个组 sequences[-1].append(idx) expected_next += 1 else: # 连续中断,新建序列组追加到列表末尾 sequences.append([idx]) expected_next = idx + 1
更高效的向量化实现方案
逐行遍历的方式在处理小批量数据时没问题,但如果筛选后的节点量达到十万甚至百万级,逐行Python循环的性能会很差。完全可以用pandas的向量化操作实现连续序列切分,核心逻辑是把“和前一个索引差值为1”作为连续的判断依据,差值不为1的位置作为分组切分点,不需要手动写循环:
实现代码:
same_width_nodes = df.loc[df['count'] == width] node_indices = same_width_nodes.sort_index().index if len(node_indices) == 0: sequences = [] else: # 计算每个位置和前一个索引的差值,差值不等于1就是新组的起点 group_flag = (node_indices - node_indices.shift(1) != 1).cumsum() # 按组聚合收集索引,转成普通列表就是最终的嵌套结构 sequences = node_indices.groupby(group_flag).apply(list).tolist()
方案优势:
- 全程基于pandas底层的C实现计算,没有逐行Python逻辑,大尺度数据下性能比循环方案高10~100倍
- 自动适配乱序的输入,只要提前对索引做排序即可,不需要手动维护计数器、越界判断
- 逻辑完全贴合连续序列的数学定义,不会因为循环逻辑的疏漏出现分组错误
内容的提问来源于stack exchange,提问作者Coder1
相关产品推荐
相关产品推荐

