【问题标题】:Add rows with specific values in between existing rows在现有行之间添加具有特定值的行
【发布时间】:2019-01-18 21:00:10
【问题描述】:

我有曲棍球数据,名为df

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

如何在每一行之后创建行,留下 57 * 2(114 行),但我新创建的行中的值取决于 event_rinkside 列。

  • 如果event_rinkside等于R,那么,我想将82插入coords_x,将0插入coords_y
  • 如果event_rinkside等于L,那么,我想将-82插入coords_x,将0插入coords_y

我觉得这个SO question的解决方案是一个很好的起点,但我不知道如何结合自己的条件:

这是我正在谈论的解决方案:

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

【问题讨论】:

    标签: r dplyr purrr


    【解决方案1】:

    这是dplyr的解决方案:

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

    工作原理:

    在第一步中,mutate 用于修改df 的未分配副本。 coords_x 列的值为 82;如果event_rinkside == "L",则该值乘以-1,否则乘以1。 coords_y 列的值为 0。

    在下一步中,未更改的原始数据框df 及其当前未分配和修改的副本与rbind 合并。这里,. 表示上述mutate 步骤的结果。 rbind 的结果是原始版本的行高于修改版本的行。

    在最后一步中,arrange 用于根据event_index 的值对行进行排序。这样一来,每个原始行后面直接跟着相应的修改行。

    结果:

    # 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
    

    【讨论】:

    • 你能解释一下导致这个的逻辑吗?
    • 一步步看懂了。 Sven mutated coords_xcoords_y 具有所需的值:R 的 (82, 0) 和 L 的 (-82, 0)。然后,他将原始数据集附加到 rbind 然后 arrange d通过 event_index 以我想要的方式格式化数据集。真的很简单,但很棒
    • @NelsonGon 我添加了解释。
    • @JasonBaik 我添加了解释。
    【解决方案2】:

    我对 r 不太熟悉,无论如何我的算法都应该可以工作。您想将该行向上移动到 2n-1 行。我将创建第二个数组并手动将它们放置在特定索引处。

    给你一些伪代码(我通常用 python 编写,所以我的伪代码显示它)

    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)
    

    您可以在循环中插入新创建的行,或者在知道它们都位于偶数索引处之后添加它们。

    【讨论】:

      【解决方案3】:

      这与Sven的回答类似,使用case_when区分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
      )
      

      如果您知道变量的范围,可以将其简化为if_elses。

      【讨论】:

        【解决方案4】:

        我的尝试,已经与其他答案非常相似,

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-05-09
          • 1970-01-01
          • 2011-07-04
          • 1970-01-01
          • 2019-09-25
          • 1970-01-01
          • 2019-05-26
          • 1970-01-01
          相关资源
          最近更新 更多