Python案例:判断上半场是否有进球
这是一个常见的足球数据分析案例,下面我用 Python 演示如何判断上半场是否有进球。

案例背景
假设我们有一批比赛数据,需要判断每场比赛上半场(前45分钟)是否有进球。
示例代码
import pandas as pd
# 模拟比赛事件数据
data = {
'match_id': [1, 1, 1, 2, 2, 3, 3, 3, 4],
'minute': [23, 45, 67, 12, 78, 30, 55, 90, 88],
'team': ['A', 'B', 'A', 'A', 'B', 'B', 'A', 'B', 'A'],
'event': ['goal', 'goal', 'goal', 'goal', 'goal', 'goal', 'goal', 'goal', 'goal']
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)
原始数据:
match_id minute team event
0 1 23 A goal
1 1 45 B goal
2 1 67 A goal
3 2 12 A goal
4 2 78 B goal
5 3 30 B goal
6 3 55 A goal
7 3 90 B goal
8 4 88 A goal
筛选上半场进球
# 筛选上半场(<=45分钟)的进球
first_half_goals = df[(df['minute'] <= 45) & (df['event'] == 'goal')]
# 统计每场比赛上半场进球数
result = first_half_goals.groupby('match_id').size().reset_index(name='上半场进球数')
# 所有比赛ID
all_matches = pd.DataFrame({'match_id': df['match_id'].unique()})
# 合并,没有进球的填0
result = all_matches.merge(result, on='match_id', how='left').fillna(0)
result['上半场进球数'] = result['上半场进球数'].astype(int)
# 判断是否有进球
result['上半场是否有进球'] = result['上半场进球数'] > 0
print(result)
match_id 上半场进球数 上半场是否有进球
0 1 2 True
1 2 1 True
2 3 1 True
3 4 0 False
用 groupby + any() 直接判断
# 更简洁的写法
is_first_half_goal = (
df.assign(上半场=df['minute'] <= 45)
.groupby('match_id')['上半场']
.apply(lambda x: True) # 占位
)
# 推荐写法:按场次聚合,判断是否存在上半场进球
result = df.groupby('match_id').apply(
lambda g: ((g['minute'] <= 45) & (g['event'] == 'goal')).any()
).reset_index(name='上半场是否有进球')
print(result)
match_id 上半场是否有进球
0 1 True
1 2 True
2 3 True
3 4 False
封装成函数(便于复用)
def check_first_half_goal(df, minute_threshold=45):
"""
判断每场比赛上半场是否有进球
参数:
df: 包含 match_id, minute, event 的 DataFrame
minute_threshold: 上半场时间界限,默认45分钟
返回:
DataFrame: 每场比赛上半场是否有进球
"""
result = (
df.groupby('match_id')
.apply(lambda g: ((g['minute'] <= minute_threshold) &
(g['event'] == 'goal')).any())
.reset_index(name='上半场是否有进球')
)
return result
# 使用
print(check_first_half_goal(df))
关键点说明
| 要点 | 说明 |
|---|---|
| 时间界限 | 通常上半场判定为 minute <= 45,若包含补时可用 <= 45+ 或 <= 45.5 |
| 事件类型 | 需筛选 event == 'goal',避免乌龙球、点球等需按业务调整 |
| 缺失场次 | 用 merge(how='left') 保证没有进球的比赛也出现,填 0 处理 |
| any() 与 sum() | 只要判断"是否有",用 any() 更高效;要看进球数用 size() 或 sum() |
扩展:含补时的情况
如果有"45+2"这种格式的数据:
def parse_minute(m):
"""解析 '45+2' 格式为数字"""
if isinstance(m, str) and '+' in m:
base, extra = m.split('+')
return int(base) + int(extra)
return int(m)
df['minute_num'] = df['minute'].apply(parse_minute)
# 上半场判断:minute_num <= 45 + 补时上限(比如5分钟)
result = df.groupby('match_id').apply(
lambda g: ((g['minute_num'] <= 45) & (g['event'] == 'goal')).any()
)
这样就能准确判断每场比赛上半场是否有进球产生了,需要我针对具体的比赛数据格式(比如从 API 或 CSV 读取)再写一个完整流程吗?