Каков наиболее эффективный способ извлечения некоторых чисел из точки данных в R? (Плюс другие конкретные шаги!)

#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)

Моя цель — преобразовать этот фрейм данных таким образом, чтобы на каждый забитый гол, за игру, приходилось по одной строке, вот так: введите описание изображения здесь

Основные проблемы, как я их вижу:

  1. *_goal_mins Поля считываются как строки, содержащие как числа, так и NAs
  2. Репликация строк таким образом, чтобы комбинации хозяев / гостей имели такое же количество строк, что и общее количество голов в этом матче

Что касается (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 библиотеку, которую вы могли бы сделать

  1. приведите home_goal_mins и away_goal_mins в том же столбце, используя pivot_longer .
  2. Разделите данные на пробелы и разделите цели в отдельных строках
  3. Удаление NA значений
  4. arrange данные на основе метки времени
  5. Получение данных в широком формате.
 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