简体   繁体   中英

Combing data frame rows in R based on common values

Given a data frame:

    > df <- data.frame( L=c('a','b','b'), t0=c(1,10,20), t1=c(9,19,39))
    > df
      L t0 t1
    1 a  1  9
    2 b 10 19
    3 b 20 39

    I want:
    > df
        L t0 t1
      1 a  1  9
      2 b 10 39

The identical values for df$L equals "b" signify that the start (t0) of the first instance of 'b' should be the new 't0' value and the new 't1' value of the last instance of (contiguous) 'b' should be the new 't1' value. In effect, if t0 and t1 are times, then I want to merge the time durations of adjacent rows that have the same value for 'L'.

After grouping by 'L', summarise to take the first value of 't0' and last value of 't1' (or min and max )

df %>%
   group_by(L) %>%
    summarise(t0 = first(t0), t1 = last(t1))
# A tibble: 2 x 3
#  L        t0    t1
#  <fct> <dbl> <dbl>
#1 a         1     9
#2 b        10    39

Based on the OP's comments, if we are also grouping by adjacent similar elements in 'L', use rleid

library(data.table)
df1 %>% 
    group_by(grp = rleid(L), L) %>%
    summarise(t0 = first(t0), t1 = last(t1))

data

df1 <- data.frame( L=c('a','b','b','a','b','b'), 
        t0=c(1,10,20,40,60,70), t1=c(9,19,39,49,69,79))

You can split by L and return the range .

df <- do.call(rbind, lapply(split(df[-1], df[1]), range))
df
#  [,1] [,2]
#a    1    9
#b   10   39

df <- data.frame(L=rownames(df), t0=df[,1], t1=df[,2])
df
#  L t0 t1
#a a  1  9
#b b 10 39

Maybe you can try aggreate and merge

res <- merge(aggregate(t0 ~ L,df,min),aggregate(t1 ~ L,df,max))

such that

> res
  L t0 t1
1 a  1  9
2 b 10 39

Using data.table :

library(data.table)
setDT(df)
df[, .(t0 = t0[1], t1 = t1[.N]), by = L]

#    L t0 t1
# 1: a  1  9
# 2: b 10 39

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM