使用不同的行和列减去函数

时间:2018-04-24 17:02:08

标签: r

我有一个这样的数据框:

   ROW     ID   ORDER       START      FINISH
    1      A      1           0            1
    2      A      1           2            4
    3      B      1           0            2
    4      A      2           4            5
    5      B      2           2            5
    6      B      2           6            8

我想创建一个新列,每行减去类似的内容:

START[x] - FINISH[x-1] 

其中x是ROW并且如果ORDER或ID被更改则返回NA,这将是结果:(考虑按ORDER排序的数据帧而不是ID)

  ROW     ID   ORDER         START       FINISH      NEW
    1      A      1           0            1        NA (first value) 
    2      A      1           2            4          1
    3      B      1           0            2        NA(changed ID) 
    4      A      2           4            5        NA(changed Order) 
    5      B      2           2            3        NA(changed ID) 
    6      B      2           6            8          3

我是R的新手,所以我无法弄明白该怎么做......

2 个答案:

答案 0 :(得分:2)

在dplyr中,这是一个分组mutate,滞后FINISH

library(dplyr)

df <- data_frame(ROW = 1:6, 
                 ID = c("A", "A", "B", "A", "B", "B"), 
                 ORDER = c(1L, 1L, 1L, 2L, 2L, 2L), 
                 START = c(0L, 2L, 0L, 4L, 2L, 6L), 
                 FINISH = c(1L, 4L, 2L, 5L, 5L, 8L))

df2 <- df %>% 
    group_by(ID, ORDER) %>% 
    mutate(NEW = START - lag(FINISH))

df2
#> # A tibble: 6 x 6
#> # Groups:   ID, ORDER [4]
#>     ROW ID    ORDER START FINISH   NEW
#>   <int> <chr> <int> <int>  <int> <int>
#> 1     1 A         1     0      1    NA
#> 2     2 A         1     2      4     1
#> 3     3 B         1     0      2    NA
#> 4     4 A         2     4      5    NA
#> 5     5 B         2     2      5    NA
#> 6     6 B         2     6      8     1

您可以使用split-apply-combine方法在基础R中执行相同的操作,但它并不能很好地阅读:

df2 <- do.call(rbind, 
               lapply(split(df, interaction(df$ID, df$ORDER)), 
                      function(x){
                          x$NEW <- x$START - c(NA, x$FINISH[-nrow(x)]); 
                          x
                      }))

df2
#>       ROW ID ORDER START FINISH NEW
#> A.1.1   1  A     1     0      1  NA
#> A.1.2   2  A     1     2      4   1
#> B.1     3  B     1     0      2  NA
#> A.2     4  A     2     4      5  NA
#> B.2.5   5  B     2     2      5  NA
#> B.2.6   6  B     2     6      8   1

请注意,FINISH的第五个元素在问题的输入和输出数据中有所不同,这就是NEW的结果在第6行中变化的原因。但逻辑仍然存在。

答案 1 :(得分:0)

data.table

library(data.table)
setDT(df)
df[,NEW := START-shift(FINISH),by=.(ID,ORDER)]

#    ROW ID ORDER START FINISH NEW
# 1:   1  A     1     0      1  NA
# 2:   2  A     1     2      4   1
# 3:   3  B     1     0      2  NA
# 4:   4  A     2     4      5  NA
# 5:   5  B     2     2      5  NA
# 6:   6  B     2     6      8   1