3
votes

Ajouter des lignes avec des valeurs spécifiques entre les lignes existantes

J'ai des données de hockey, appelées df

library(purrr)
df %>%
  group_by(id) %>%
  map_dfr(rbind, NA) %>%
  mutate(id = rep(df$id, each = 2))

Comment puis-je créer des lignes après chaque ligne, me laissant avec 57 * 2 (114 lignes), mais les valeurs de mes lignes nouvellement créées dépendent de la colonne event_rinkside .

  • Si event_rinkside vaut R , alors, je souhaite insérer 82 dans coords_x et 0 dans coords_y .
  • Si event_rinkside est égal à L , alors, je veux insérer -82 dans coords_x et 0 en coords_y .

Je pense que la solution à cette question SO a> est un bon point de départ, mais je ne sais pas comment incorporer mes propres conditions:

Voici la solution dont je parle:

structure(list(event_index = 1:57, coords_x = c(80, 53, 31, -56, 
-34, -33, -40, 30, -66, -36, 45, 17, -6, 47, -51, -31, -69, -86, 
-70, 80, 65, -76, -71, 81, -57, 80, 75, 77, -71, -40, -83, 62, 
77, 76, NA, -61, 69, -45, 68, 31, 58, 61, 80, 34, 80, -85, -37, 
-57, 76, 14, 49, -82, -34, -36, -83, -84, -55), coords_y = c(-1, 
14, -30, 17, 26, -23, -37, 17, -32, -18, 25, 17, -38, 21, 28, 
22, 17, 13, 10, -37, -17, 9, 18, -11, 21, -7, 3, 3, -38, 31, 
8, -30, -2, 4, NA, -5, 15, 10, -30, -34, 20, 27, -4, 8, -18, 
19, 32, -21, 0, 40, -4, -30, -24, -28, -2, -3, 34), event_rinkside = c("R", 
"R", "R", "L", "L", "L", "L", "R", "L", "L", "R", "N", "N", "R", 
"L", "L", "L", "L", "L", "R", "R", "L", "L", "R", "L", "R", "R", 
"R", "L", "L", "L", "R", "R", "R", NA, "L", "R", "L", "R", "R", 
"R", "R", "R", "R", "R", "L", "L", "L", "R", "N", "R", "L", "L", 
"L", "L", "L", "L")), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -57L))


0 commentaires

4 Réponses :


0
votes

Je ne suis pas trop familier avec r, mon algorithme devrait fonctionner indépendamment de cela. Vous souhaitez déplacer la ligne vers la ligne 2n-1. Je créerais un deuxième tableau et les placerais manuellement dans les index spécifiques.

un pseudo code pour vous (j'écris généralement en python donc mon pseudo le montre)

reinsert(list):
   array_out = [len(list)*2,len(list[0]) // initialize to the desired dimensions 
   array_out[0] = list[0]  /// manually insert first row cause math
   for n in range(0,len(list)):
      array_out[2n-1] = list[n] 
      array_out[2n] = event_rinkside // make a function call or make an ifthen clause to do you logic
   return(array_out)

vous pouvez insérer les lignes nouvellement créées dans la boucle ou les ajouter après le fait sachant qu'ils seront tous à des index pairs.


0 commentaires

2
votes

Voici une solution avec dplyr :

# A tibble: 114 x 4
   event_index coords_x coords_y event_rinkside
         <int>    <dbl>    <dbl> <chr>         
 1           1       80       -1 R             
 2           1       82        0 R             
 3           2       53       14 R             
 4           2       82        0 R             
 5           3       31      -30 R             
 6           3       82        0 R             
 7           4      -56       17 L             
 8           4      -82        0 L             
 9           5      -34       26 L             
10           5      -82        0 L             
# … with 104 more rows

Comment ça marche:

Dans la première étape, mutate est utilisé pour modifier une copie non attribuée de df . La colonne coords_x prend la valeur 82; la valeur est multipliée par -1 si event_rinkside == "L" et 1 sinon. La colonne coords_y prend la valeur 0.

À l'étape suivante, le bloc de données d'origine inchangé df et la copie actuelle non attribuée et modifiée de celui-ci sont combinés avec rbind . Ici, . représente le résultat de l'étape mutate ci-dessus. Le résultat de rbind a les lignes de la version originale au-dessus des lignes de la version modifiée.

Dans la dernière étape, arrange est utilisé pour trier les lignes le long des valeurs de event_index . De cette façon, chaque ligne d'origine est directement suivie de la ligne modifiée correspondante.

Le résultat:

library(dplyr)

df %>%
  mutate(coords_x = 82 * ifelse(event_rinkside == "L", -1, 1),
         coords_y = 0) %>%
  rbind(df, .) %>%
  arrange(event_index)


4 commentaires

Pourriez-vous expliquer la logique qui a conduit à cela?


Je l'ai compris après l'avoir parcouru pas à pas. Sven muter d coords_x et coords_y avec les valeurs souhaitées: (82, 0) pour R et (-82, 0) pour L. Puis , il a joint le jeu de données d'origine avec rbind puis arrange d par event_index pour formater le jeu de données de la manière que je voulais. Vraiment simple, mais brillant


@NelsonGon J'ai ajouté une explication.


@JasonBaik J'ai ajouté une explication.



0
votes

Ceci est similaire à la réponse de Sven, en utilisant case_when pour distinguer les possibilités dans event_rinkside:

new_df <- df %>% bind_rows(
  df %>% mutate(
    coords_x = case_when(
      event_rinkside == 'R' ~  82,
      event_rinkside == 'L' ~ -82,
      TRUE                  ~ coords_x
    ),
    coords_y = case_when(
      event_rinkside == 'R' ~ 0,
      event_rinkside == 'L' ~ 0,
      TRUE                  ~ coords_y
    )
  )
) %>% arrange(
  event_index
)

Si vous connaissez les plages de vos variables, il pourrait être simplifié en if_elses.


0 commentaires

0
votes

Ma tentative, qui est assez similaire à d'autres réponses déjà,

df <- df[rep(1:nrow(df), each = 2),] ## Create a duplicate row after each row

df[seq(2,nrow(df),2),] <- df[seq(2,nrow(df),2),] %>% mutate(coords_x = case_when(event_rinkside == "R" ~ 82,
                                                        event_rinkside == "L" ~ -82,
                                                        TRUE ~ coords_x),
                                   coords_y = case_when(event_rinkside == "R" ~ 0,
                                                        event_rinkside == "L" ~ 0,
                                                        TRUE ~ coords_y)
)


0 commentaires