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

如何在Python中统计相邻同值点并按计数分组标记

问题描述

现有以下Python测试脚本,生成随机0-1矩阵并以红/黄背景可视化:

import numpy as np
import pandas as pd

# Generating dummy data for testing
ROWS=10
COLS=20
X = np.random.randint(2, size=(ROWS, COLS))

# Visualizing
df = pd.DataFrame(data=X)
bg='background-color: '
df.style.apply(lambda x: [bg+'red' if v>=1 else bg+'yellow' for v in x])

需求:对每行中无间隔的相邻同值元素进行分组,统计每组的元素数量,并为每个元素标记对应的组编号和计数,最终可视化区分不同组。

解决方案

可以通过逐行识别连续同值段生成分组标记,再结合样式可视化区分组。以下是两种实现方式:

方式1:纯Python循环实现(直观易懂)

import numpy as np
import pandas as pd

# 生成测试数据
ROWS = 10
COLS = 20
X = np.random.randint(2, size=(ROWS, COLS))
df = pd.DataFrame(data=X)

# 为每行生成连续同值分组标记
def mark_consecutive_groups(row):
    marks = []
    if len(row) == 0:
        return marks
    
    current_val = row.iloc[0]
    count = 1
    group_num = 1
    
    for val in row.iloc[1:]:
        if val == current_val:
            count += 1
        else:
            marks.extend([f"组{group_num}({count})"] * count)
            current_val = val
            count = 1
            group_num += 1
    # 处理最后一组
    marks.extend([f"组{group_num}({count})"] * count)
    return marks

# 生成标记DataFrame
mark_df = df.apply(mark_consecutive_groups, axis=1, result_type='expand')

# 自定义样式:按组分配不同背景色
def style_groups(row):
    bg = 'background-color: '
    # 定义组对应的背景色(可根据需要扩展)
    color_map = {
        "组1": "#ffcccc", "组2": "#ccffcc", "组3": "#ccccff",
        "组4": "#ffffcc", "组5": "#ffccff", "组6": "#ccffff"
    }
    styles = []
    for mark in mark_df.loc[row.name]:
        group_prefix = mark.split('(')[0]
        # 若组编号超过预设,用白色兜底
        color = color_map.get(group_prefix, "#ffffff")
        styles.append(f"{bg}{color}")
    return styles

# 合并原始数据与标记,应用样式展示
combined_df = pd.concat([df, mark_df], axis=1, keys=['原始值', '分组标记'])
combined_df.style.apply(style_groups, axis=1)

方式2:Numpy优化实现(效率更高)

利用np.diff快速定位值变化的位置,适合处理大规模数据:

def mark_consecutive_groups_np(row):
    row_np = row.to_numpy()
    # 找到值发生变化的索引位置
    change_indices = np.where(np.diff(row_np) != 0)[0] + 1
    # 将行分割为连续同值的段
    segments = np.split(row_np, change_indices)
    # 生成标记
    marks = []
    for group_idx, seg in enumerate(segments, 1):
        marks.extend([f"组{group_idx}({len(seg)})"] * len(seg))
    return marks

# 生成标记DataFrame
mark_df_np = df.apply(mark_consecutive_groups_np, axis=1, result_type='expand')

# 样式应用与方式1一致,直接复用style_groups函数即可
combined_df_np = pd.concat([df, mark_df_np], axis=1, keys=['原始值', '分组标记'])
combined_df_np.style.apply(style_groups, axis=1)

说明

  • 两种方式都会为每个元素生成类似组1(3)的标记,其中组1是组编号,3是该组的连续同值元素数量。
  • 样式函数通过组编号分配不同背景色,直观区分不同的连续同值组。
  • 若需要仅标记原始值的样式(不显示标记文本),可直接对原始DataFrame应用style_groups逻辑,跳过合并标记的步骤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 04:17:12