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

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

     cname year govstruct
6091 China 1960         3
6092 China 1961         3
6093 China 1962         3
6094 China 1963         3
6095 China 1964         3
6096 China 1965         3
6097 China 1966         3
6098 China 1967         3
6099 China 1968         3
6100 China 1969         3
6101 China 1970         3
6102 China 1971         3
6103 China 1972         3
6104 China 1973         3
6105 China 1974         3
6106 China 1975         3
6107 China 1976         3
6108 China 1977         3
6109 China 1978         3
6110 China 1979         3
6111 China 1980         3
6112 China 1981         3
6113 China 1982         3
6114 China 1983         1
6115 China 1984         1
6116 China 1985         1
6117 China 1986         1
6118 China 1987         1
6119 China 1988         1
6120 China 1989         1
6121 China 1990         1
6122 China 1991         1
6123 China 1992         1
6124 China 1993         1
6125 China 1994         1
6126 China 1995         1
6127 China 1996         1
6128 China 1997         1
6129 China 1998         1
6130 China 1999         1
6131 China 2000         1
6132 China 2001         1
6133 China 2002         1
6134 China 2003         1
6135 China 2004         1
6136 China 2005         1
6137 China 2006         3
6138 China 2007         3
6139 China 2008         3
6140 China 2009         3
6141 China 2010         3
6142 China 2011         3
6143 China 2012         3


Я хочу создать набор данных, который будет отмечать диапазон дат, охватываемых govstruct.

То, что я хотел бы, является набором данных, который отмечает название страны, диапазон лет и ценность govstruct. Таким образом, окончательный набор данных выглядит следующим образом:

cname    years  govstruct
China 1960-1982    3
China 1983-2005    1
China 2006-2012    3

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

Большое спасибо за вашу помощь.

Ответы [ 2 ]

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

Вот один вариант с dplyr/data.table, где мы группируем по 'cname' и run-length-id из 'govstruct', и summarise по paste по range из 'year'

library(dplyr)
library(stringr)
library(data.table)
df1 %>% 
    group_by(cname, grp = rleid(govstruct)) %>%
    summarise(govstructure = first(govstruct), 
         years = str_c(range(year), collapse="-"))  %>%
    ungroup %>%
    select(-grp)
# A tibble: 3 x 3
#  cname govstructure years    
#  <chr>        <int> <chr>    
#1 China            3 1960-1982
#2 China            1 1983-2005
#3 China            3 2006-2012

Или мы также можем построить grp, основываясь на сравнении соседних элементов

df1 %>%
   group_by(cname, grp = cumsum(c(TRUE, diff(govstruct) != 0))) %>%
   summarise(govstructure = first(govstruct), 
         years = str_c(range(year), collapse="-")) 

или используя data.table, используя тот же метод, что и в dplyr. т.е. сгруппированные по rleid из 'govstruct' и 'cname' paste * range из 'year'

library(data.table)
setDT(df1)[ , .(govstructure = first(govstruct),
      year = paste(range(year), collapse = "-")), 
      .(cname, grp = rleid(govstruct))][, grp := NULL][]
#  cname govstructure      year
#1: China            3 1960-1982
#2: China            1 1983-2005
#3: China            3 2006-2012

или другой вариант с base R

grp <- with(rle(df1$govstruct), rep(seq_along(values), lengths))
aggregate(year ~ cname + grp, data = df1, 
      FUN = function(x) paste(range(x), collapse="-"))

данные

df1 <- structure(list(cname = c("China", "China", "China", "China", 
"China", "China", "China", "China", "China", "China", "China", 
"China", "China", "China", "China", "China", "China", "China", 
"China", "China", "China", "China", "China", "China", "China", 
"China", "China", "China", "China", "China", "China", "China", 
"China", "China", "China", "China", "China", "China", "China", 
"China", "China", "China", "China", "China", "China", "China", 
"China", "China", "China", "China", "China", "China", "China"
), year = 1960:2012, govstruct = c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 3L, 3L, 3L)), 
class = "data.frame", row.names = c(NA, 
-53L))
1 голос
/ 05 февраля 2020

Мы можем использовать от data.table до paste значений first и last year для каждого cname и значения кодировки длины серии govstruct.

library(data.table)

setDT(df)[ , .(year = paste(first(year), last(year), sep = "-"), 
           govstruct = first(govstruct)), .(cname, rleid(govstruct))]


#   cname rleid      year govstruct
#1: China     1 1960-1982         3
#2: China     2 1983-2005         1
#3: China     3 2006-2012         3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...