R объединить строки с одинаковыми значениями - PullRequest
0 голосов
/ 13 мая 2018

У меня есть датафрейм, и значения строк сначала упорядочены от наименьшего к наибольшему.Я вычисляю различия в значениях строк между соседними строками, комбинирую строки с одинаковыми различиями (например, меньше 1) и возвращаю усредненные значения объединенных строк.Я мог бы проверить различия в каждой строке с помощью цикла for, но, похоже, это очень неэффективный способ.Есть идеи получше?Спасибо.

library(dplyr)
DF <- data.frame(ID=letters[1:12],
                 Values=c(1, 2.2, 3, 5, 6.2, 6.8, 7, 8.5, 10, 12.2, 13, 14))
DF <- DF %>%
   mutate(Diff=c(0, diff(Values)))

Ожидаемый результат DF будет

ID        Values
a         1.0
b/c       2.6  # (2.2+3.0)/2
d         5.0
e/f/g     6.67 # (6.2+6.8+7.0)/3
h         8.5
i         10.0
j/k       12.6 # (12.2+13.0)/2
i         14.0

Ответы [ 3 ]

0 голосов
/ 13 мая 2018

Рассчитайте разницу между Values каждой строки и проверьте, равны ли они >= 1.Совокупная сумма этого >=1 даст вам отдельную группу, в которой можно summarize получить желаемый результат.

library(dplyr)
DF %>% arrange(Values) %>%
  group_by(Diff = cumsum(c(1,diff(Values)) >= 1) ) %>%
  summarise(ID = paste0(ID, collapse = "/"), Values = mean(Values)) %>%
  ungroup() %>% select(-Diff)

# # A tibble: 8 x 2
# ID    Values
# <chr>  <dbl>
# 1 a       1.00
# 2 b/c     2.60
# 3 d       5.00
# 4 e/f/g   6.67
# 5 h       8.50
# 6 i      10.0 
# 7 j/k    12.6 
# 8 l      14.0 
0 голосов
/ 13 мая 2018

Вот вариант с data.table

library(data.table)
setDT(DF)[, .(ID = toString(ID), Values = round(mean(Values), 2)),
          by = .(Diff = cumsum(c(TRUE, diff(Values)>=1)))][, -1, with = FALSE]
#        ID Values
#1:       a   1.00
#2:    b, c   2.60
#3:       d   5.00
#4: e, f, g   6.67
#5:       h   8.50
#6:       i  10.00
#7:    j, k  12.60
#8:       l  14.00
0 голосов
/ 13 мая 2018
library(magrittr)

df <- DF[order(DF$Values),]
df$Values %>% 
  #Find groups for each row
  outer(., ., function(x, y) x >= y & x < y + 1) %>% 
  # Remove sub-groups
  `[<-`(apply(., 1, cumsum) > 1, F) %>%              
  # Remove sub-group columns
  .[, colSums(.) > 0] %>%                            
  # select these groups from data
  apply(2, function(x) data.frame(ID = paste(df$ID[x], collapse = '/')
                                , Values = mean(df$Values[x]))) %>% 
  # bind results by row
  do.call(what = rbind)

# ID    Values
# 1      a  1.000000
# 2    b/c  2.600000
# 4      d  5.000000
# 5  e/f/g  6.666667
# 8      h  8.500000
# 9      i 10.000000
# 10   j/k 12.600000
# 12     l 14.000000

Примечание:

Этот метод отличается от тех, которые используют diff, поскольку он группирует строки только в том случае, если все Значения находятся в пределах <1 друг от друга. </p>

Пример:

Измените набор данных так, чтобы Значение было 7,3 при идентификаторе г.

Вышеописанный метод: идентификаторы e, f и g больше не группируются, поскольку значение для идентификатора e равно 6,2 и 7,2 - 6,2> 1.

Метод различий: идентификаторы e, f и g по-прежнему сгруппированы, поскольку разность идентификаторов для e и f составляет <1, а разность идентификаторов F и G составляет <1 </p>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...