#r #string #performance #dataframe #vector
#r #строка #Производительность #dataframe #вектор
Вопрос:
У меня довольно специфическая проблема, для которой я могу найти очень сложное решение, но я надеюсь, что кто-нибудь сможет изложить немного более элегантный метод.
У меня есть CSV-файл, состоящий из одной строки для каждого сыгранного исторического футбольного матча. Поля, о которых я забочусь, выглядят примерно так:
home_team <- c("Team A", "Team B", "Team B")
away_team <- c("Team C", "Team C", "Team D")
home_goals <- c(2, 0, 1)
away_goals <- c(1, 2, 0)
home_goal_mins <- c("5 60", "NA", "80")
away_goal_mins <- c("15", "20 40", "NA")
df <- data.frame(home_team, away_team, home_goals, away_goals, home_goal_mins, away_goal_mins,
stringsAsFactors = FALSE)
df
#> home_team away_team home_goals away_goals home_goal_mins away_goal_mins
#> 1 Team A Team C 2 1 5 60 15
#> 2 Team B Team C 0 2 NA 20 40
#> 3 Team B Team D 1 0 80 NA
Создано 2020-10-05 пакетом reprex (версия 0.3.0)
Моя цель — преобразовать этот фрейм данных таким образом, чтобы на каждый забитый гол, за игру, приходилось по одной строке, вот так:
Основные проблемы, как я их вижу:
*_goal_mins
Поля считываются как строки, содержащие как числа, так и NAs- Репликация строк таким образом, чтобы комбинации хозяев / гостей имели такое же количество строк, что и общее количество голов в этом матче
Что касается (1), я использовал stringr::str_split(., " ")
для извлечения чисел, но затем изо всех сил пытался преобразовать их в числовой вектор. Взяв df
в качестве примера первую строку, я изо всех сил пытаюсь преобразовать "5 60"
в c(5, 60)
, и мне становится все труднее, когда я пытаюсь объединить команды хозяев "5 60"
и "15"
гостей, чтобы получить полную последовательность целей c(5, 15, 60)
.
Что касается (2), мой текущий подход заключается в вычислении total_goals_scored
каждого совпадения и выполнении следующего:
expanded_df <- df[rep(seq_len(dim(df)[1]),
df$total_goals_scored), ]
но я чувствую, что может быть лучший метод.
Любая помощь или советы будут оценены! Спасибо
Ответ №1:
Используя dplyr
и tidyr
библиотеку, которую вы могли бы сделать
- приведите
home_goal_mins
иaway_goal_mins
в том же столбце, используяpivot_longer
. - Разделите данные на пробелы и разделите цели в отдельных строках
- Удаление
NA
значений arrange
данные на основе метки времени- Получение данных в широком формате.
library(dplyr)
library(tidyr)
df %>%
pivot_longer(cols = c(home_goal_mins, away_goal_mins)) %>%
separate_rows(value, sep = ' ', convert = TRUE) %>%
filter(!is.na(value)) %>%
arrange(home_team, away_team, value) %>%
group_by(home_team, away_team) %>%
mutate(row = row_number()) %>%
pivot_wider()
# home_team away_team home_goals away_goals row home_goal_mins away_goal_mins
# <chr> <chr> <dbl> <dbl> <int> <int> <int>
#1 Team A Team C 2 1 1 5 NA
#2 Team A Team C 2 1 2 NA 15
#3 Team A Team C 2 1 3 60 NA
#4 Team B Team C 0 2 1 NA 20
#5 Team B Team C 0 2 2 NA 40
#6 Team B Team D 1 0 1 80 NA