基于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
相关产品推荐
相关产品推荐

