Суммирующие ряды 1 и 0 в кадре данных в R - PullRequest
0 голосов
/ 04 февраля 2020

Я хотел бы написать R-код для суммирования серий 1 и 0 (в основном мне нужно применить кодирование длины серии к столбцу «Значения») в кадре данных, но мне нужно сохранить информацию о столбце «ID» .

Это пример кадра данных, который необходимо суммировать:

> df
   ID Values
1   1      0
2   2      0
3   3      0
4   4      1
5   5      1
6   6      1
7   7      1
8   8      0
9   9      0
10 10      0
11 11      1
12 12      0
13 13      0
14 14      1
15 15      0
16 16      0

Это ожидаемый результат:

> df
  ID lengths values
1  1       3      0
2  4       4      1
3  8       3      0
4 11       1      1
5 12       2      0
6 14       1      1
7 15       2      0

Может кто-нибудь помочь мне написать это эффективно?

Спасибо!

Ответы [ 4 ]

2 голосов
/ 04 февраля 2020

Вы можете легко сделать это, используя группировку data.table и функцию rleid:

library(data.table)
setDT(df)
df[, .(ID = ID[1], lengths = .N, values = Values[1]), by = rleid(Values)]
#   rleid ID lengths values
#1:     1  1       3      0
#2:     2  4       4      1
#3:     3  8       3      0
#4:     4 11       1      1
#5:     5 12       2      0
#6:     6 14       1      1
#7:     7 15       2      0
1 голос
/ 04 февраля 2020

Вот решение с базой R:

r <- rle(df$Values)

data.frame(ID=df$ID[1+cumsum(c(0, head(r$lengths, -1)))], r$lengths, r$values)
# > data.frame(ID=df$ID[1+cumsum(c(0, head(r$lengths, -1)))], r$lengths, r$values)
#   ID r.lengths r.values
# 1  1         3        0
# 2  4         4        1
# 3  8         3        0
# 4 11         1        1
# 5 12         2        0
# 6 14         1        1
# 7 15         2        0
1 голос
/ 04 февраля 2020
library(tidyverse)

df %>%
  group_by(group = cumsum(Values != lag(Values, default = first(Values)))) %>%  
  summarise(ID = min(ID),
            lengths = n(),
            values = unique(Values)) %>%
  select(-group)

# # A tibble: 7 x 3
#      ID lengths values
#   <int>   <int>  <int>
# 1     1       3      0
# 2     4       4      1
# 3     8       3      0
# 4    11       1      1
# 5    12       2      0
# 6    14       1      1
# 7    15       2      0
0 голосов
/ 04 февраля 2020

Другая dplyr версия, которая может быть проще для понимания:

df %>%
    mutate(doesValueChange = Values - lag(Values) != 0) %>%
    mutate(doesValueChange = replace_na(doesValueChange, FALSE)) %>%
    mutate(sequenceNr = cumsum(doesValueChange)) %>%
    group_by(sequenceNr) %>%
    summarise(ID = first(ID)
              , lengths = n()
              , Values = first(Values))
...