Повернуть табличку в широкий формат на основе нескольких строк

Вот мои данные:

game_id     team      opponent    steals    assists
       <int> <chr>     <chr>           <chr>  <chr>  
 1 401468360 Spurs     Warriors        6      18     
 2 401468360 Warriors  Spurs           9      35     
 3 401468358 Clippers  Rockets         6      25     
 4 401468358 Rockets   Clippers        11     20     
 5 401468359 Hawks     Bucks           4      23     
 6 401468359 Bucks     Hawks           4      21     
 7 401468356 Thunder   Celtics         4      21     
 8 401468356 Celtics   Thunder         15     25     
 9 401468357 Suns      Heat            9      22     
10 401468357 Heat      Suns            6      3     

Как мне получить эти данные в следующем формате?

game_id     team     opponent     team_steals   opp_assists   team_assists   opp_steals
       <int> <chr>     <chr>          <int>       <chr>         <chr>         <chr>
 1 401468360 Spurs     Warriors        6           9              18            35
 2 401468358 Clippers  Rockets         6           11             25            20
 3 401468359 Hawks     Bucks           4           4              23            21
 4 401468356 Thunder   Celtics         4           15             21            25
 9 401468357 Suns      Heat            9           6              22            23

Я пробовал несколько вариантов pivot_wider безрезультатно. Я даже не уверен, что эта функция выполнит то, что я ищу.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
0
60
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Что-то вроде этого:

library(dplyr)
library(tidyr)
df %>%
  group_by(game_id) %>% 
  rename(team_steals = steals) %>% 
  mutate(opp_steals = lead(team_steals)) %>% 
  rename(team_assists = assists) %>% 
  mutate(opp_assists = lead(team_assists)) %>% 
  drop_na()
    game_id team     opponent team_steals team_assists opp_steals opp_assists
      <int> <chr>    <chr>          <int>        <int>      <int>       <int>
1 401468360 Spurs    Warriors           6           18          9          35
2 401468358 Clippers Rockets            6           25         11          20
3 401468359 Hawks    Bucks              4           23          4          21
4 401468356 Thunder  Celtics            4           21         15          25
5 401468357 Suns     Heat               9           22          6           3

Это предполагает, что в следующей строке всегда отображается одно и то же совпадение с поменявшимися местами команда/противник. Не лучшее предположение.

M-- 15.11.2022 19:14

Я согласен. Но данные в этом варианте использования упорядочены группами по два, первая — команда, а вторая — противник. В случае, если структура отличается, мы могли бы внести ее в эту структуру.

TarJae 15.11.2022 19:16

Я бы предположил, что это не в этом конкретном порядке, и использовал group_by или arrange (не особо задумывался), чтобы сделать ваше решение надежным.

M-- 15.11.2022 19:29

Вариант с использованием pivot_wider с некоторой обработкой данных может выглядеть так:

library(dplyr, w = FALSE)
library(tidyr)

dat |>
  group_by(game_id) |>
  mutate(foo = c("team", "opp"), across(c(team, opponent), first)) |>
  ungroup() |> 
  tidyr::pivot_wider(names_from = foo, values_from = c(steals, assists), names_glue = "{foo}_{.value}")
#> # A tibble: 5 × 7
#>     game_id team     opponent team_steals opp_steals team_assists opp_assists
#>       <int> <chr>    <chr>          <int>      <int>        <int>       <int>
#> 1 401468360 Spurs    Warriors           6          9           18          35
#> 2 401468358 Clippers Rockets            6         11           25          20
#> 3 401468359 Hawks    Bucks              4          4           23          21
#> 4 401468356 Thunder  Celtics            4         15           21          25
#> 5 401468357 Suns     Heat               9          6           22           3

ДАННЫЕ

dat <- structure(list(game_id = c(
  401468360L, 401468360L, 401468358L,
  401468358L, 401468359L, 401468359L, 401468356L, 401468356L, 401468357L,
  401468357L
), team = c(
  "Spurs", "Warriors", "Clippers", "Rockets",
  "Hawks", "Bucks", "Thunder", "Celtics", "Suns", "Heat"
), opponent = c(
  "Warriors",
  "Spurs", "Rockets", "Clippers", "Bucks", "Hawks", "Celtics",
  "Thunder", "Heat", "Suns"
), steals = c(
  6L, 9L, 6L, 11L, 4L, 4L,
  4L, 15L, 9L, 6L
), assists = c(
  18L, 35L, 25L, 20L, 23L, 21L, 21L,
  25L, 22L, 3L
)), class = "data.frame", row.names = c(
  "1", "2",
  "3", "4", "5", "6", "7", "8", "9", "10"
))

Это решение лучше!

TarJae 15.11.2022 19:16

Этот код тоже гениален: across(c(team, opponent), first) не могли бы вы прокомментировать это?! Удаление этой строки даст тот же промежуточный результат во второй строке, но конечный результат будет другим, содержащим строки с NA.

TarJae 15.11.2022 19:23

@TarJae Сначала я думал, что смогу сделать простой pivot_wider. Однако, поскольку имя команды и соперника переключаются с первого ряда на второй, это не сработает. Отсюда использование across(c(team, opponent), first), чтобы у нас были одинаковые имена в каждой строке для game_id. Кстати: ИМХО лучше или хуже - неправильные термины. Первое: создайте работающее решение. Во-вторых: придумайте более элегантное решение во время второй или... попытки. (:

stefan 15.11.2022 19:33

Привет, ребята, это был самый точный и быстрый ответ, который я мог бы попросить. Спасибо всем за понимание и помощь. Я все еще новичок в R, но я очарован тем, насколько он мощный. Какой ответ я отмечаю как правильный? РЖУ НЕ МОГУ.

Aaron Morris 15.11.2022 22:01
Ответ принят как подходящий
library(dplyr)

dat %>% 
  right_join(dat, by = c("game_id", "team" = "opponent", "opponent" = "team"), 
                  suffix = c("_team", "_opponent")) %>% 
  distinct(game_id, .keep_all = TRUE)
#>     game_id     team opponent steals_team steals_opponent assists_team  assists_opponent
#> 1 401468360    Spurs Warriors           6               9           18                35
#> 2 401468358 Clippers  Rockets           6              11           25                20
#> 3 401468359    Hawks    Bucks           4               4           23                21
#> 4 401468356  Thunder  Celtics           4              15           21                25
#> 5 401468357     Suns     Heat           9               6           22                 3

Другие вопросы по теме