Как захватить диапазон непоследовательных чисел в r - PullRequest
1 голос
/ 05 февраля 2020

Я работаю с данными временных рядов, которые выглядят следующим образом:

     Missing_Years       cname
1263          1960 Afghanistan
1264          1961 Afghanistan
1265          1962 Afghanistan
1266          1963 Afghanistan
1267          1964 Afghanistan
1268          1997 Afghanistan
1269          1998 Afghanistan
1270          1999 Afghanistan
1271          2000 Afghanistan
1272          2001 Afghanistan
1273          2002 Afghanistan
1274          2003 Afghanistan
1275          2004 Afghanistan
1276          2005 Afghanistan

Мне нужен набор данных, в котором указаны название страны и диапазон лет. Если вы заметили, даты не являются последовательными. Поэтому использование только функции range было бы неточным. Это сложная часть.

Я бы хотел, чтобы результат выглядел примерно так:

   cname          Missing_Years
Afghanistan       1960 - 1964 
Afghanistan       1997 - 2005 

Обратите внимание, что я буду циклически повторять страны. Поэтому любой код, который можно сделать таким образом, будет очень признателен.

Большое спасибо за помощь!

Ответы [ 2 ]

1 голос
/ 05 февраля 2020

Мы также можем использовать data.table

library(data.table)
setDT(df)[, .(cname = first(cname), Missing_Years = paste(range(Missing_Years),
      collapse="_")), .(grp = cumsum(Missing_Years - shift(Missing_Years, 
         fill = first(Missing_Years)) > 1 ))][, grp := NULL][]
#         cname Missing_Years
#1: Afghanistan     1960_1964
#2: Afghanistan     1997_2005

data

df <- structure(list(Missing_Years = c(1960L, 1961L, 1962L, 1963L, 
1964L, 1997L, 1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 
2005L), cname = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L), .Label = "Afghanistan", class = "factor")), class = 
"data.frame", row.names = c(NA,-14L))
1 голос
/ 05 февраля 2020

Вы можете узнать строки, где разрывы последовательности, используя diff и использовать его как переменную группировки.

df$group <- cumsum(c(TRUE, diff(df$Missing_Years) > 1))
aggregate(Missing_Years~cname+group, df, function(x) paste(range(x),collapse = "-"))

Или, используя dplyr, мы можем сравнить значения, используя lag.

library(dplyr)

df %>%
  group_by(cname,grp = cumsum(Missing_Years-lag(Missing_Years,default = 0) > 1)) %>%
  summarise(Missing_Years = paste(range(Missing_Years),  collapse = "-")) %>%
  select(-grp)

#  cname       Missing_Years
#  <fct>       <chr>        
#1 Afghanistan 1960-1964    
#2 Afghanistan 1997-2005    

данные

df <- structure(list(Missing_Years = c(1960L, 1961L, 1962L, 1963L, 
1964L, 1997L, 1998L, 1999L, 2000L, 2001L, 2002L, 2003L, 2004L, 
2005L), cname = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L), .Label = "Afghanistan", class = "factor")), class = 
"data.frame", row.names = c(NA,-14L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...