Python统计表格颜色列相邻组合时红绿与绿红计数相同问题排查
问题背景
需要统计指定表格中Color列的相邻行颜色组合出现次数,统计规则如下:
- 相邻两行均为绿色:
greengreen计数+1 - 前一行为绿色、后一行为红色:
greenred计数+1 - 前一行为红色、后一行为绿色:
redgreen计数+1 - 相邻两行均为红色:
redred计数+1
参考表格截图:
原实现代码如下:
finalData['Color'] greengreen = 0 greenred = 0 redgreen = 0 redred=0 for i in range(len(finalData)): if i < (len(finalData)-1): if finalData['Color'][i] == 'green' and finalData['Color'][i+1] == 'green': greengreen += 1 elif finalData['Color'][i] == 'green' and finalData['Color'][i+1] == 'red': greenred += 1 elif finalData['Color'][i] == 'red' and finalData['Color'][i+1] == 'green': redgreen += 1 elif finalData['Color'][i] == 'red' and finalData['Color'][i+1] == 'red': redred += 1 else: print('?') print("Value of greengreen bricks: ",greengreen) print("Value of greenred bricks: ",greenred) print("Value of redred bricks: ",redred) print("Value of redgreen bricks: ",redgreen)
运行代码后出现异常:greenred和redgreen的计数结果始终相等,无法区分两种顺序不同的跨色组合。例如某次运行输出为:greengreen=1、greenred=2、redred=6、redgreen=2,结果不符合预期。
问题原因
核心问题出在pandas Series的取值逻辑上:
你用finalData['Color'][i]取值时,默认匹配的是索引标签等于i的元素,不是表格中位置为i的行。如果之前对表格做过筛选、删除行、合并等操作,DataFrame的默认整数索引会出现断层、不连续的情况,此时循环i从0递增取值时,取到的根本不是位置相邻的两行数据,取值错位会导致统计逻辑完全失效,出现跨色计数相等的假象。
你可以在原循环中加入打印语句print(i, finalData['Color'][i], finalData['Color'][i+1]),运行后就能直观看到取值和实际表格顺序不符的问题。
修复方案
方案1:转原生列表规避索引问题(最稳妥)
先把Color列转为原生Python列表,列表的索引是连续的位置索引,不会出现pandas标签索引的错位问题:
# 转为原生列表 color_list = finalData['Color'].tolist() greengreen = greenred = redgreen = redred = 0 # 直接循环到倒数第二个元素,无需额外判断i范围 for i in range(len(color_list) - 1): cur_color = color_list[i] next_color = color_list[i+1] if cur_color == 'green' and next_color == 'green': greengreen += 1 elif cur_color == 'green' and next_color == 'red': greenred += 1 elif cur_color == 'red' and next_color == 'green': redgreen += 1 elif cur_color == 'red' and next_color == 'red': redred += 1 else: print(f"未识别的颜色组合:{cur_color} -> {next_color}") print("Value of greengreen bricks: ",greengreen) print("Value of greenred bricks: ",greenred) print("Value of redred bricks: ",redred) print("Value of redgreen bricks: ",redgreen)
方案2:用iloc按位置取值(保留pandas结构)
如果不想转列表,使用pandas的.iloc方法按位置索引取值,也能避开标签索引的坑:
color_col = finalData['Color'] greengreen = greenred = redgreen = redred = 0 for i in range(len(color_col) - 1): # iloc是按位置取,i就是行的实际位置 cur_color = color_col.iloc[i] next_color = color_col.iloc[i+1] if cur_color == 'green' and next_color == 'green': greengreen += 1 elif cur_color == 'green' and next_color == 'red': greenred += 1 elif cur_color == 'red' and next_color == 'green': redgreen += 1 elif cur_color == 'red' and next_color == 'red': redred += 1 else: print(f"未识别的颜色组合:{cur_color} -> {next_color}")
方案3:pandas原生高效写法(无手动循环)
用pandas内置的移位、分组方法实现统计,运行效率更高,也不会出现索引问题:
import pandas as pd # 生成相邻下一行的颜色列 finalData['next_color'] = finalData['Color'].shift(-1) # 过滤掉最后一行(无下一行数据,next_color为空) pair_data = finalData.dropna(subset=['next_color']) # 按颜色对分组计数 count_result = pair_data.groupby(['Color', 'next_color']).size() # 提取对应组合的计数,不存在则返回0 greengreen = count_result.get(('green', 'green'), 0) greenred = count_result.get(('green', 'red'), 0) redgreen = count_result.get(('red', 'green'), 0) redred = count_result.get(('red', 'red'), 0)
内容的提问来源于stack exchange,提问作者Nidal Zd
相关产品推荐
相关产品推荐

