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

基于Pandas实现会话内动作-页码组合单次计数的方案问询

解决方法:按会话分组去重计数

我明白你的需求了——要把数据按会话划分,每个会话里的「动作-页码」组合不管出现多少次都只计数1次。下面我一步步带你实现这个需求:

步骤1:准备数据并添加会话ID

首先你的示例数据里没有会话标识,我们得先从enter和exit来划分会话:每次enter开启新会话,直到exit结束。先把你的示例数据整理成标准的DataFrame:

import pandas as pd

# 整理你的示例数据(空页码用NaN表示)
data = [
    {'action': 'enter', 'page_number': pd.NA},
    {'action': 'next', 'page_number': 1},
    {'action': 'prev', 'page_number': 2},
    {'action': 'next', 'page_number': 1},
    {'action': 'next', 'page_number': 2},
    {'action': 'exit', 'page_number': 3},
    {'action': 'enter', 'page_number': pd.NA},
    {'action': 'next', 'page_number': 1},
    {'action': 'error', 'page_number': pd.NA},
    {'action': 'next', 'page_number': 1},
    {'action': 'error', 'page_number': pd.NA},
    {'action': 'error', 'page_number': pd.NA},
    {'action': 'error', 'page_number': pd.NA},
    {'action': 'next', 'page_number': 2},
    {'action': 'prev', 'page_number': 3},
    {'action': 'prev', 'page_number': 2},
    {'action': 'next', 'page_number': 1},
    {'action': 'prev', 'page_number': 2},
    {'action': 'prev', 'page_number': 1},
    {'action': 'exit', 'page_number': 0},
    {'action': 'enter', 'page_number': pd.NA},
    {'action': 'exit', 'page_number': pd.NA}
]

df = pd.DataFrame(data)

接下来给数据添加会话ID,这是处理会话类数据的核心步骤:

# 标记所有会话开始的行(action为enter)
start_mask = df['action'] == 'enter'
# 累加生成会话ID,每次出现enter就开启新会话
df['session_id'] = start_mask.cumsum()

步骤2:生成「动作-页码」组合标识

把action和page_number合并成你想要的格式,空页码的动作直接保留原名:

def format_action(row):
    if pd.notna(row['page_number']):
        return f"{row['action']}(page number = {row['page_number']})"
    else:
        return row['action']

# 生成组合后的动作列
df['action_combined'] = df.apply(format_action, axis=1)

步骤3:按会话分组去重计数

现在对每个会话提取唯一的动作组合,每个组合只计数1次:

# 按会话分组,提取每组的唯一动作组合,再统计计数
session_counts = df.groupby('session_id')['action_combined'].apply(
    lambda x: pd.Series(x.unique()).value_counts()
)

# 整理成你期望的格式
session_counts = session_counts.reset_index().rename(columns={
    'level_1': 'action',
    'action_combined': '计数'
})

如果你想单独查看每个会话的结果,可以这样输出:

# 逐个会话打印结果
for session_id in df['session_id'].unique():
    print(f"=== 会话 {session_id} ===")
    print(session_counts[session_counts['session_id'] == session_id][['action', '计数']])
    print("\n")

示例输出(会话1)

运行后会话1的结果和你期望的完全一致:

action                  计数
enter                   1
next(page number = 1)   1
prev(page number = 2)   1
next(page number = 2)   1
exit(page number = 3)   1

关键说明

  • 会话划分:用cumsum()对enter行累加生成会话ID,这是处理会话类数据的经典技巧,能自动识别会话边界。
  • 去重逻辑:用unique()提取每个会话内的唯一动作组合,天然满足「出现多次仅算1次」的需求。
  • 空值处理:通过pd.notna()判断页码是否为空,保证enter、error这类无页码的动作正常显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 20:07:54