#r #dataframe #dplyr
#r #фрейм данных #dplyr
Вопрос:
У меня есть большой фрейм данных с несколькими столбцами, но для этого запроса меня интересуют 3 столбца.
df <- structure(list(country = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "ireland", class = "factor"),
parameter = structure(c(2L, 1L, 3L, 2L, 1L, 3L, 2L, 1L, 3L,2L, 1L, 3L), .Label = c("rainfall", "temp", "wind"), class = "factor"),
value = c(10L, 15L, 20L, 9L, 18L, 10L, 12L, 25L, 15L, 10L, 10L, 20L), unit = structure(c(3L, 2L, 1L, 3L, 2L, 1L, 3L,
2L, 1L, 3L, 2L, 1L), .Label = c("km/hr", "mm", "oC"), class = "factor")), class = "data.frame", row.names = c(NA, -12L))
country parameter value unit
ireland temp 10 oC
ireland rainfall 15 mm
ireland wind 20 km/hr
ireland temp 9 oC
ireland rainfall 18 mm
ireland wind 10 km/hr
ireland temp 12 oC
ireland rainfall 25 mm
ireland wind 15 km/hr
ireland temp 10 oC
ireland rainfall 10 mm
ireland wind 20 km/hr
Я хочу сгруппировать по стране и параметру, чтобы извлечь строки, в которых столбец значений последовательно увеличивается в 3 или более раз.
Пример вывода desire.
country parameter value unit
ireland rainfall 15 mm
ireland rainfall 18 mm
ireland rainfall 25 mm
ireland wind 10 km/hr
ireland wind 15 km/hr
ireland wind 20 km/hr
Комментарии:
1.
diff()
предоставляет разницу между одним значением и следующим в списке. Возможно, проверка наdiff(df) > 3
? После васsort(df, decreasing=TRUE)
, конечно.2. Почему у вас есть для
wind
последних 20? Есть два значения по 20, поэтому разница равна нулю. Правильно ли там иметь 20?
Ответ №1:
Вы можете сгруппировать по стране и параметру, и они создадут третью группирующую переменную для значений, которые не меньше запаздывающего значения, затем отфильтруйте группы размером 3 или больше:
library(dplyr)
df %>%
group_by(country, parameter) %>%
group_by(x = cumsum(value <= lag(value, default = FALSE)), .add = TRUE) %>%
filter(n() >= 3) %>%
ungroup() %>%
arrange(country, parameter) %>%
select(-x)
# A tibble: 6 x 4
country parameter value unit
<fct> <fct> <int> <fct>
1 ireland rainfall 15 mm
2 ireland rainfall 18 mm
3 ireland rainfall 25 mm
4 ireland wind 10 km/hr
5 ireland wind 15 km/hr
6 ireland wind 20 km/hr
Комментарии:
1. Это выглядит великолепно, но некорректно работает с моим фактическим фреймом данных, и я не уверен, почему. Я попытался преобразовать свои столбцы в коэффициенты и промежуточные. Использование разных групп столбцов по комбинациям. Я даже просто вернул его обратно в группу только по параметру. Возвращаемые результаты включают отбрасывания после последовательного увеличения.
2. В пределах страны и групп параметров будут возвращены все экземпляры с 3 или более последовательно возрастающими значениями. Вам нужен только первый набор этих значений? из вашего поста не ясно.
3. Если значения продолжают увеличиваться, да. Если есть падение, я не хочу, чтобы об этом сообщалось. Я хочу значения, которые выглядят как 1,2,3,4,5, а не 1,2,3,1,1,2,1. Надеюсь, это имеет больше смысла.
4. Да, но как насчет 1,2,3,1,2,3,4,1,2 — что бы вы хотели вернуть в этом случае? Вы хотите 1,2,3, потому что это первый набор последовательно увеличивающихся значений, или 1,2,3,4, потому что он самый длинный, или оба?
5. Оба. Но в текущей форме я получаю: (непосредственно из выходных данных в моем df) 7,16, 30, 10, 1, 7,13, 15, 30…… 10 должны были отфильтроваться?
Ответ №2:
Вот базовый вариант R, использующий subset
ave
rle
subset(
df[with(df,order(country, parameter)), ],
!!ave(value, country, parameter, FUN = function(x) with(rle(cumsum(c(1, diff(x) <= 0))), rep(lengths >= 3, lengths)))
)
что дает
country parameter value unit
2 ireland rainfall 15 mm
5 ireland rainfall 18 mm
8 ireland rainfall 25 mm
6 ireland wind 10 km/hr
9 ireland wind 15 km/hr
12 ireland wind 20 km/hr
Ответ №3:
df %>%
group_by(country, parameter) %>%
mutate(
flag = c(0, diff(value)) > 0,
flag_lag = lead(flag),
seq_end = flag == TRUE amp; flag_lag %in% c(NA, FALSE),
seq_begin = flag == FALSE amp; flag_lag == TRUE,
) %>%
slice(if(length(which(seq_begin == TRUE):which(seq_end == TRUE)) >= 3) which(seq_begin == TRUE):which(seq_end == TRUE) else NA) %>%
select(-contains("flag"), -contains("seq"))
Комментарии:
1.
lag()
болееmutate
удобен, поскольку вам не придется вручную присваивать первое значение.
Ответ №4:
Вот решение, использующее dplyr
df %>%
arrange(value,decreasing = FALSE) %>% # Arrange by value
filter(lag(value) > 3) # And filter for a difference above 3 in value
df
country parameter value unit
1 ireland temp 10 oC
2 ireland wind 10 km/hr
3 ireland temp 10 oC
4 ireland rainfall 10 mm
5 ireland temp 12 oC
6 ireland rainfall 15 mm
7 ireland wind 15 km/hr
8 ireland rainfall 18 mm
9 ireland wind 20 km/hr
10 ireland wind 20 km/hr
11 ireland rainfall 25 mm