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

如何在R中基于日期、球队及赛事计算球队连胜记录?

Solution for Calculating Win Streaks in R

Let's break this down into clear, efficient steps that work well even for your 30k+ row dataset. We'll use the tidyverse suite (dplyr + tidyr) for fast, readable data manipulation.

Step 1: Prepare the Data

First, we'll convert the date factor to a proper Date type and sort the data chronologically—this is critical for accurate streak calculations.

library(tidyverse)
library(lubridate) # For date parsing

# Load your dataset (using the dput you provided)
df <- structure(list(Date = structure(c(3L, 10L, 12L, 2L, 7L, 13L, 4L, 8L, 9L, 4L, 11L, 1L, 5L, 6L), .Label = c("03/10/2018", "04/10/2018", "04/11/2018", "09/10/2018", "10/11/2018", "13/09/2018", "16/09/2018", "16/10/2018", "20/09/2018", "21/10/2018", "22/10/2018", "28/09/2018", "30/09/2018"), class = "factor"), Home.Team = structure(c(1L, 3L, 1L, 2L, 3L, 2L, 3L, 1L, 3L, 1L, 2L, 3L, 2L, 3L), .Label = c("Everton", "Liverpool", "Man C"), class = "factor"), Away.Team = structure(c(7L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 1L, 4L, 2L, 3L, 5L, 6L), .Label = c("Arsenal", "Bournemouth", "Chelsea", "Man C", "Watford", "West Ham", "Wolves" ), class = "factor"), Competition = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 2L, 2L, 2L, 1L, 2L, 2L), .Label = c("Cup", "League" ), class = "factor"), Home.Goals = c(1L, 3L, 0L, 3L, 6L, 5L, 1L, 1L, 3L, 0L, 3L, 6L, 5L, 1L), Away.Goals = c(3L, 1L, 2L, 0L, 0L, 0L, 0L, 3L, 1L, 2L, 0L, 0L, 0L, 0L)), .Names = c("Date", "Home.Team", "Away.Team", "Competition", "Home.Goals", "Away.Goals" ), class = "data.frame", row.names = c(NA, -14L))

# Clean and sort data
df_clean <- df %>%
  mutate(Date = dmy(Date)) %>% # Parse dd/mm/yyyy format
  arrange(Date) %>%
  mutate(Match_ID = row_number()) # Add a unique ID for merging later

Step 2: Calculate Each Streak Type

We'll compute the four required streaks one by one, then merge them back into the original dataset.

1. Home Team's Home Win Streak

This counts consecutive home wins by the home team before the current match:

home_streaks <- df_clean %>%
  group_by(Home.Team) %>%
  mutate(
    home_win = ifelse(Home.Goals > Away.Goals, 1, 0),
    # Group consecutive wins/losses
    streak_group = cumsum(home_win != lag(home_win, default = 0)),
    # Calculate current streak length (includes current match if won)
    current_home_streak = ifelse(home_win == 1, sequence(rle(streak_group)$lengths), 0),
    # Streak BEFORE the current match: subtract 1 if current match is a win, else 0
    home_streak_before = ifelse(home_win == 1, current_home_streak - 1, 0)
  ) %>%
  ungroup() %>%
  select(Match_ID, home_streak_before)

2. Away Team's Away Win Streak

Same logic, but for the away team's consecutive away wins:

away_streaks <- df_clean %>%
  group_by(Away.Team) %>%
  mutate(
    away_win = ifelse(Away.Goals > Home.Goals, 1, 0),
    streak_group = cumsum(away_win != lag(away_win, default = 0)),
    current_away_streak = ifelse(away_win == 1, sequence(rle(streak_group)$lengths), 0),
    away_streak_before = ifelse(away_win == 1, current_away_streak - 1, 0)
  ) %>%
  ungroup() %>%
  select(Match_ID, away_streak_before)

3. Home Team's Total Win Streak (Home + Away)

We need to include all matches the home team has played (as home or away) to calculate their overall streak:

home_total_streaks <- bind_rows(
  # All matches where the team is home
  df_clean %>% select(Date, Team = Home.Team, Win = ifelse(Home.Goals > Away.Goals, 1, 0), Match_ID, is_home = TRUE),
  # All matches where the team is away
  df_clean %>% select(Date, Team = Away.Team, Win = ifelse(Away.Goals > Home.Goals, 1, 0), Match_ID, is_home = FALSE)
) %>%
  arrange(Date, Match_ID) %>%
  group_by(Team) %>%
  mutate(
    streak_group = cumsum(Win != lag(Win, default = 0)),
    current_total_streak = ifelse(Win == 1, sequence(rle(streak_group)$lengths), 0),
    total_streak_before = ifelse(Win == 1, current_total_streak - 1, 0)
  ) %>%
  ungroup() %>%
  filter(is_home) %>% # Keep only rows where the team is the home team
  select(Match_ID, home_total_streak_before = total_streak_before)

4. Away Team's Total Win Streak (Home + Away)

Mirror the total streak logic for the away team:

away_total_streaks <- bind_rows(
  df_clean %>% select(Date, Team = Home.Team, Win = ifelse(Home.Goals > Away.Goals, 1, 0), Match_ID, is_away = FALSE),
  df_clean %>% select(Date, Team = Away.Team, Win = ifelse(Away.Goals > Home.Goals, 1, 0), Match_ID, is_away = TRUE)
) %>%
  arrange(Date, Match_ID) %>%
  group_by(Team) %>%
  mutate(
    streak_group = cumsum(Win != lag(Win, default = 0)),
    current_total_streak = ifelse(Win == 1, sequence(rle(streak_group)$lengths), 0),
    total_streak_before = ifelse(Win == 1, current_total_streak - 1, 0)
  ) %>%
  ungroup() %>%
  filter(is_away) %>% # Keep only rows where the team is the away team
  select(Match_ID, away_total_streak_before = total_streak_before)

Step 3: Merge All Streaks into the Final Dataset

Combine all the calculated streaks back into the cleaned original data:

final_df <- df_clean %>%
  left_join(home_streaks, by = "Match_ID") %>%
  left_join(away_streaks, by = "Match_ID") %>%
  left_join(home_total_streaks, by = "Match_ID") %>%
  left_join(away_total_streaks, by = "Match_ID") %>%
  select(-Match_ID) # Remove the temporary match ID

# View the result
print(final_df)

Key Notes

  • Efficiency: This approach uses vectorized operations (no loops) which is fast enough for 30k+ rows.
  • Chronological Order: We sorted the data first to ensure streak calculations follow the correct timeline.
  • Streak Definition: The columns show the number of consecutive wins before the current match (not including the current match if it's a win). If you want to include the current match, just remove the -1 in the streak_before calculations.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 18:08:11