#r #change-tracking
#r #отслеживание изменений
Вопрос:
У меня есть набор данных, который отслеживал числовые изменения в разных типах объектов с течением времени. Итак, у меня есть столбцы для идентификатора, измерения, года и изменения. Столбец изменений содержит ИСТИННЫЕ значения для произошедшего изменения по сравнению с его предыдущим значением. все, что является постоянным до и после этого значения, помечается как FALSE, если не произойдет другого изменения.
Я хочу иметь возможность выполнять следующие действия:
- уметь устанавливать пороговое значение. Поэтому отметьте все случаи значений, которые перешли за определенное число. Например, если пороговое значение равно 5, то отметьте все, что было выше или ниже этого, но не отмечайте случаи, которые изменились только с 2 на 4, например.
- создайте столбец с изменением значения. Например, -2 для уменьшения изменения с 5 до 3 и 2 для увеличения с 5 до 7.
# <chr> <int> <int> <lgl> # 1 A 2 2019-2 FALSE # 2 A 2 2019-3 FALSE # 3 A 2 2019-4 FALSE # 4 A 5 2019-5 TRUE # 5 A 5 2019-5 FALSE # 6 A 4 2019-8 TRUE # 7 A 4 2019-9 TRUE # 8 B 23 2019-5 FALSE # 9 B 7 2019-9 TRUE #10 B 7 2020-5 FALSE # … with 11 more rows
Ответ №1:
Это dplyr
решение позволяет вам получить сумму изменения в столбце, а также создаст логический столбец, в который вы попадете TRUE
, если пороговое значение будет превышено в любом направлении. Например, в строке 4 значение увеличилось с 2 до 5, поэтому пороговое значение было превышено. Однако в строке 5 значение остается равным 5, и поэтому пороговое значение не было преодолено между строками 4 и 5. Когда мы переходим к строке 6, значение упало до 4, что ниже порогового значения, поэтому мы снова попадаем TRUE
в эту строку.
Я установил пороговое значение 4.5 для ясности.
library(dplyr)
threshold <- 4.5
df %>%
group_by(group) %>%
mutate(change_amount = c(0, diff(value)),
crossed_thresh = sign(lag(value - threshold)) !=
sign(value - threshold),
crossed_thresh = ifelse(is.na(crossed_thresh), FALSE,
crossed_thresh))
#> # A tibble: 10 x 6
#> # Groups: group [2]
#> group value month change change_amount crossed_thresh
#> <chr> <int> <chr> <lgl> <dbl> <lgl>
#> 1 A 2 2019-2 FALSE 0 FALSE
#> 2 A 2 2019-3 FALSE 0 FALSE
#> 3 A 2 2019-4 FALSE 0 FALSE
#> 4 A 5 2019-5 TRUE 3 TRUE
#> 5 A 5 2019-5 FALSE 0 FALSE
#> 6 A 4 2019-8 TRUE -1 TRUE
#> 7 A 4 2019-9 TRUE 0 FALSE
#> 8 B 23 2019-5 FALSE 0 FALSE
#> 9 B 7 2019-9 TRUE -16 FALSE
#> 10 B 7 2020-5 FALSE 0 FALSE
Данные
df <- structure(list(group = c("A", "A", "A", "A", "A", "A", "A", "B",
"B", "B"), value = c(2L, 2L, 2L, 5L, 5L, 4L, 4L, 23L, 7L, 7L),
month = c("2019-2", "2019-3", "2019-4", "2019-5", "2019-5",
"2019-8", "2019-9", "2019-5", "2019-9", "2020-5"), change = c(FALSE,
FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE
)), class = "data.frame", row.names = c(NA, -10L))
df
#> group value month change
#> 1 A 2 2019-2 FALSE
#> 2 A 2 2019-3 FALSE
#> 3 A 2 2019-4 FALSE
#> 4 A 5 2019-5 TRUE
#> 5 A 5 2019-5 FALSE
#> 6 A 4 2019-8 TRUE
#> 7 A 4 2019-9 TRUE
#> 8 B 23 2019-5 FALSE
#> 9 B 7 2019-9 TRUE
#> 10 B 7 2020-5 FALSE
Комментарии:
1. Спасибо @AllanCameron
Ответ №2:
библиотека data.table может быть полезной, в частности, ее функция сдвига.
#reproduction of dataset
df <- data.table(col1 = c('A','A','A','A','A','A','A','A','A','A'),
col2 = c(2,2,2,5,5,4,4,23,7,7))
Добавьте два столбца
1-й мы проверяем, идентична ли строка предыдущей
df[,Identical :=(col2 == shift(col2)) ]
2-й мы добавляем разницу значений к предыдущему
df[,change := col2 - shift(col2, 1)]
Это дает желаемый результат
col1 col2 Identical change
1: A 2 NA NA
2: A 2 TRUE 0
3: A 2 TRUE 0
4: A 5 FALSE 3
5: A 5 TRUE 0
6: A 4 FALSE -1
7: A 4 TRUE 0
8: A 23 FALSE 19
9: A 7 FALSE -16
10: A 7 TRUE 0